diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3234056239..d588c0dd13 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -146,7 +146,7 @@ jobs: else if [[ ${{ github.ref }} == refs/pull/* ]] then - DESCRIPTION="PR#$(echo ${{ github.ref }} | sed -e 's#refs/pull/##' -e 's#/merge##')" + DESCRIPTION="PR$(echo ${{ github.ref }} | sed -e 's#refs/pull/##' -e 's#/merge##')" elif [[ ${{ github.ref }} == refs/heads/* ]] then DESCRIPTION="$(echo ${{ github.ref }} | sed -e 's#refs/heads/##')" diff --git a/Assets/Editor/BuildTiltBrush.cs b/Assets/Editor/BuildTiltBrush.cs index 259ba578b2..a8af77a93d 100644 --- a/Assets/Editor/BuildTiltBrush.cs +++ b/Assets/Editor/BuildTiltBrush.cs @@ -1032,7 +1032,7 @@ public TempSetAppNames(BuildTarget target, string Description) #endif if (!String.IsNullOrEmpty(Description)) { - new_name += "-(" + Description + ")"; + new_name += "-(" + Description.Replace("#", "") + ")"; new_identifier += "-" + Description.Replace("_", "").Replace("#", "").Replace("-", ""); } if (m_IsAndroidOrIos) diff --git a/Assets/Editor/DummyCommandRefs.cs b/Assets/Editor/DummyCommandRefs.cs index a0aee72faa..4a0bf27bac 100644 --- a/Assets/Editor/DummyCommandRefs.cs +++ b/Assets/Editor/DummyCommandRefs.cs @@ -179,15 +179,15 @@ public static void Prefabs_Panels_MemoryWarningPanel() public static void Prefabs_Panels_PolyPanel() { Use(GlobalCommands.LoginToGenericCloud); - Use(GlobalCommands.ViewPolyGallery); - Use(GlobalCommands.ViewPolyPage); + Use(GlobalCommands.ViewBlocksGallery); + Use(GlobalCommands.ViewIcosaHomePage); } public static void Prefabs_Panels_PolyPanel_Mobile() { Use(GlobalCommands.LoginToGenericCloud); - Use(GlobalCommands.ViewPolyGallery); - Use(GlobalCommands.ViewPolyPage); + Use(GlobalCommands.ViewBlocksGallery); + Use(GlobalCommands.ViewIcosaHomePage); } public static void Prefabs_Panels_ReferencePanel_ReferencePanel_Mobile() diff --git a/Assets/Editor/GlTF_EditorExporter.cs b/Assets/Editor/GlTF_EditorExporter.cs index e80bb9087f..a66868aa38 100644 --- a/Assets/Editor/GlTF_EditorExporter.cs +++ b/Assets/Editor/GlTF_EditorExporter.cs @@ -20,8 +20,13 @@ using System.Text; using JetBrains.Annotations; using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using SimpleJSON; using UnityEditor; +using UnityEditor.ShaderGraph.Serialization; using UnityEngine; +using UnityGLTF; +using UnityGLTF.Extensions; using UObject = UnityEngine.Object; namespace TiltBrush @@ -95,7 +100,7 @@ private static void ExportBrushStrokes_gltf1() { new ExportGlTF().ExportBrushStrokes( GetExportBaseName() + ".gltf", - AxisConvention.kGltfAccordingToPoly, + AxisConvention.kGltfAccordingToIcosa, binary: false, doExtras: true, gltfVersion: 1, @@ -128,75 +133,135 @@ private static bool ExportBrushStrokes_Enabled() [MenuItem("Open Brush/glTF/Export Environments to glTF", false, 4)] private static void ExportEnvironments() { -#if !GAMEOBJ_EXPORT_TO_GLTF - Debug.LogError("Enable the define and fix up the code"); -#else - // Save the original RenderSettings - Environment.RenderSettingsLite originalRenderSettings = Environment.GetRenderSettings(); - - // Clear out the existing environments directory to do a clean export - string projectPath = Path.GetDirectoryName(Application.dataPath); - string environmentExportPath = Path.Combine(projectPath, - ExportUtils.kProjectRelativeEnvironmentExportRoot); - try { - Directory.Delete(environmentExportPath, recursive: true); - } catch (DirectoryNotFoundException) { - // It's okay if this directory doesn't exist yet as it will be created later. - } + // Save the original RenderSettings + Environment.RenderSettingsLite originalRenderSettings = Environment.GetRenderSettings(); - // Clear out the existing textures directory to do a clean export - string textureExportPath = Path.Combine(projectPath, - ExportUtils.kProjectRelativeTextureExportRoot); - try { - Directory.Delete(textureExportPath, recursive: true); - } catch (DirectoryNotFoundException) { - // It's okay if this directory doesn't exist yet as it will be created later. - } - if (!FileUtils.InitializeDirectoryWithUserError( - textureExportPath, "Failed to export, can't create texture export directory")) { - return; - } + // Clear out the existing environments directory to do a clean export + string projectPath = Path.GetDirectoryName(Application.dataPath); + string environmentExportPath = Path.Combine(projectPath, + ExportUtils.kProjectRelativeEnvironmentExportRoot); + try + { + Directory.Delete(environmentExportPath, recursive: true); + } + catch (DirectoryNotFoundException) + { + // It's okay if this directory doesn't exist yet as it will be created later. + } - // Get the environment - TiltBrushManifest manifest = AssetDatabase.LoadAssetAtPath("Assets/Manifest.asset"); - foreach (Environment env in manifest.Environments) { - // Copy over the RenderSettings - Environment.SetRenderSettings(env.m_RenderSettings); - - // Set up the environment - string envGuid = env.m_Guid.ToString("D"); - Debug.LogFormat("Exporting environment: {0}", env.m_RenderSettings.m_EnvironmentPrefab); - GameObject envPrefab = Resources.Load(env.m_RenderSettings.m_EnvironmentPrefab); - GameObject envGameObject = UObject.Instantiate(envPrefab); - envGameObject.name = envGuid; - - // Hide game objects that don't get exported to Poly. - foreach (Transform child in envGameObject.transform) { - if (SceneSettings.ExcludeFromPolyExport(child)) { - child.gameObject.SetActive(false); - } - } + // Clear out the existing textures directory to do a clean export + string textureExportPath = Path.Combine(projectPath, + ExportUtils.kProjectRelativeTextureExportRoot); + try + { + Directory.Delete(textureExportPath, recursive: true); + } + catch (DirectoryNotFoundException) + { + // It's okay if this directory doesn't exist yet as it will be created later. + } + if (!FileUtils.InitializeDirectoryWithUserError( + textureExportPath, "Failed to export, can't create texture export directory")) + { + return; + } - // Set up the environment export directory - string directoryName = Path.Combine(environmentExportPath, envGuid); - if (!FileUtils.InitializeDirectoryWithUserError( - directoryName, "Failed to export, can't create environment export directory")) { - return; - } + // Get the environment + TiltBrushManifest manifest = AssetDatabase.LoadAssetAtPath("Assets/Manifest.asset"); + JToken colorToJArray(Color c) => JToken.FromObject(new { c.r, c.g, c.b, c.a }); + JToken vector3ToJArray(Vector3 c) => JToken.FromObject(new { c.x, c.y, c.z }); + var envJson = new JObject(); + foreach (Environment env in manifest.Environments) + { + // Copy over the RenderSettings + Environment.SetRenderSettings(env.m_RenderSettings); + + // Set up the environment + string envGuid = env.m_Guid.ToString("D"); + var envJsonItem = new JObject(); + envJsonItem["name"] = env.name; + envJsonItem["guid"] = envGuid; + var envRenderSettingsJson = new JObject(); + envRenderSettingsJson["fogEnabled"] = env.m_RenderSettings.m_FogEnabled; + envRenderSettingsJson["fogColor"] = colorToJArray(env.m_RenderSettings.m_FogColor); + envRenderSettingsJson["fogDensity"] = env.m_RenderSettings.m_FogDensity; + envRenderSettingsJson["fogStartDistance"] = env.m_RenderSettings.m_FogStartDistance; + envRenderSettingsJson["fogEndDistance"] = env.m_RenderSettings.m_FogEndDistance; + envRenderSettingsJson["clearColor"] = colorToJArray(env.m_RenderSettings.m_ClearColor); + envRenderSettingsJson["ambientColor"] = colorToJArray(env.m_RenderSettings.m_AmbientColor); + envRenderSettingsJson["skyboxExposure"] = env.m_RenderSettings.m_SkyboxExposure; + envRenderSettingsJson["skyboxTint"] = colorToJArray(env.m_RenderSettings.m_SkyboxTint); + envRenderSettingsJson["environmentPrefab"] = env.m_RenderSettings.m_EnvironmentPrefab; + envRenderSettingsJson["environmentReverbZone"] = env.m_RenderSettings.m_EnvironmentReverbZonePrefab; + envRenderSettingsJson["skyboxCubemap"] = env.m_RenderSettings.m_SkyboxCubemap != null ? + env.m_RenderSettings.m_SkyboxCubemap.name : ""; + envRenderSettingsJson["reflectionCubemap"] = env.m_RenderSettings.m_ReflectionCubemap != null ? + env.m_RenderSettings.m_ReflectionCubemap.name : ""; + envRenderSettingsJson["reflectionIntensity"] = env.m_RenderSettings.m_ReflectionIntensity; + envJsonItem["renderSettings"] = envRenderSettingsJson; + var envLights = new JArray(); + foreach (var light in env.m_Lights) + { + var envLight = new JObject(); + envLight["color"] = colorToJArray(light.Color); + envLight["position"] = vector3ToJArray(light.m_Position); + envLight["rotation"] = vector3ToJArray(light.m_Rotation.eulerAngles); + envLight["type"] = light.m_Type.ToString(); + envLight["range"] = light.m_Range; + envLight["spotAngle"] = light.m_SpotAngle; + envLight["shadowsEnabled"] = light.m_ShadowsEnabled; + envLights.Add(envLight); - string basename = FileUtils.SanitizeFilename(envGameObject.name); - string gltfName = Path.Combine(directoryName, basename + ".gltf"); + } + envJsonItem["lights"] = envLights; + envJsonItem["teleportBoundsHalfWidth"] = env.m_TeleportBoundsHalfWidth; + envJsonItem["controllerXRayHeight"] = env.m_ControllerXRayHeight; + envJsonItem["widgetHome"] = vector3ToJArray(env.m_WidgetHome); + envJsonItem["skyboxColorA"] = colorToJArray(env.m_SkyboxColorA); + envJsonItem["skyboxColorB"] = colorToJArray(env.m_SkyboxColorB); + envJson[envGuid] = envJsonItem; + + Debug.LogFormat("Exporting environment: {0}", env.m_RenderSettings.m_EnvironmentPrefab); + GameObject envPrefab = Resources.Load(env.m_RenderSettings.m_EnvironmentPrefab); + GameObject envGameObject = UObject.Instantiate(envPrefab); + envGameObject.name = envGuid; + + // Hide game objects that don't get exported to Poly. + foreach (Transform child in envGameObject.transform) + { + if (SceneSettings.ExcludeFromPolyExport(child)) + { + child.gameObject.SetActive(false); + } + } - var exporter = new ExportGlTF(); - exporter.ExportGameObject(envGameObject, gltfName, env); + // Set up the environment export directory + string directoryName = Path.Combine(environmentExportPath, envGuid); + if (!FileUtils.InitializeDirectoryWithUserError( + directoryName, "Failed to export, can't create environment export directory")) + { + return; + } - // DestroyImmediate is required because editor mode never runs object garbage collection. - UObject.DestroyImmediate(envGameObject); - } + string basename = FileUtils.SanitizeFilename(envGameObject.name); + + var settings = GLTFSettings.GetOrCreateSettings(); + settings.UseMainCameraVisibility = false; + var context = new ExportContext(); + var unityGltfexporter = new GLTFSceneExporter(envGameObject.transform, context); + unityGltfexporter.SaveGLB(directoryName, basename + ".glb"); + + // DestroyImmediate is required because editor mode never runs object garbage collection. + UObject.DestroyImmediate(envGameObject); + } + + string jsonString = envJson.ToString(); + string path = Path.Combine(environmentExportPath, "environments.json"); + File.WriteAllText(path, jsonString); + + // Restore the original RenderSettings + Environment.SetRenderSettings(originalRenderSettings); - // Restore the original RenderSettings - Environment.SetRenderSettings(originalRenderSettings); -#endif } private static Dictionary GetBrushes() diff --git a/Assets/Editor/RenderCubeMap.cs b/Assets/Editor/RenderCubeMap.cs new file mode 100644 index 0000000000..e2a9243a7b --- /dev/null +++ b/Assets/Editor/RenderCubeMap.cs @@ -0,0 +1,69 @@ +using UnityEngine; +using UnityEditor; +using System.IO; + +public class RenderCubeMap : EditorWindow +{ + [SerializeField] + static int faceSize = 1024; + + [MenuItem("Open Brush/RenderCubeMap", false, 11)] + static void Init() + { + var cam = Camera.main; + var camPos = cam.transform.position; + var camRot = cam.transform.rotation; + + // cam.fieldOfView = 45; + // cam.farClipPlane = 4000; + // cam.allowMSAA = false; + + cam.transform.position = new Vector3(0, 10, 0); + cam.transform.rotation = Quaternion.identity; + + RenderToCubeMap(Camera.main); + + cam.transform.position = camPos; + cam.transform.rotation = camRot; + } + + static void RenderToCubeMap(Camera Cam) + { + Cubemap cubemap = new Cubemap(faceSize, TextureFormat.ARGB32, false); + + var cubeSavePath = Application.dataPath + "/cube" + ".png"; + + Cam.RenderToCubemap(cubemap, 63); + Texture2D flattenedTexture = new Texture2D(faceSize * 4, faceSize * 3, TextureFormat.ARGB32, false); + for (int i = 0; i < 6; i++) + { + int x = 0, y = 0; + switch (i) + { + case 0: x = faceSize; y = faceSize * 2; break; // Top + case 1: x = faceSize; y = 0; break; // Bottom + case 2: x = faceSize * 3; y = faceSize; break; // Right + case 3: x = 0; y = faceSize; break; // Left + case 4: x = faceSize; y = faceSize; break; // Front + case 5: x = faceSize * 2; y = faceSize; break; // Back + } + Graphics.CopyTexture(cubemap, i, 0, 0, 0, faceSize, faceSize, flattenedTexture, 0, 0, x, y); + } + + byte[] bytes = flattenedTexture.EncodeToPNG(); + DestroyImmediate(flattenedTexture, true); + File.WriteAllBytes(cubeSavePath, bytes); + + // var tex2DSavePath = Application.dataPath + "/360tex" + ".jpg"; + // renderTexCube.ConvertToEquirect(renderTex2D); + DestroyImmediate(cubemap, true); + // Texture2D tex2d = new Texture2D(faceSize, 2048, TextureFormat.RGB24,false); + // RenderTexture.active = renderTex2D; + // tex2d.ReadPixels(new Rect(0,0,renderTex2D.width, renderTex2D.height),0,0); + // DestroyImmediate(renderTex2D, true); + // tex2d.Apply(); + // bytes = tex2d.EncodeToJPG(); + // DestroyImmediate(tex2d, true); + // File.WriteAllBytes(tex2DSavePath, bytes); + } +} diff --git a/Assets/Editor/RenderCubeMap.cs.meta b/Assets/Editor/RenderCubeMap.cs.meta new file mode 100644 index 0000000000..7f77bd4a48 --- /dev/null +++ b/Assets/Editor/RenderCubeMap.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3d39ae5f85ad4334e8545bab384d79c1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Editor/SetIcosaToken.cs b/Assets/Editor/SetIcosaToken.cs new file mode 100644 index 0000000000..eb7f7b3132 --- /dev/null +++ b/Assets/Editor/SetIcosaToken.cs @@ -0,0 +1,58 @@ +// Copyright 2021 The Tilt Brush Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// 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 TiltBrush +{ + + using UnityEngine; + using UnityEditor; + + public class SetIcosaToken : EditorWindow + { + private static string key = "IcosaToken"; + private static string value = ""; + + [MenuItem("Open Brush/Icosa/Set Login Token")] + public static void ShowWindow() + { + value = PlayerPrefs.GetString(key); + GetWindow("Set Icosa Login Token"); + } + + void OnGUI() + { + GUILayout.Label("Enter Token", EditorStyles.boldLabel); + value = EditorGUILayout.TextField("Value", value); + + if (GUILayout.Button("Save")) + { + PlayerPrefs.SetString(key, value); + PlayerPrefs.Save(); + Debug.Log($"Saved: {key} = {value}"); + } + + if (GUILayout.Button("Load")) + { + value = PlayerPrefs.GetString(key, ""); + Debug.Log($"Loaded: {key} = {value}"); + } + + if (GUILayout.Button("Delete")) + { + PlayerPrefs.DeleteKey(key); + Debug.Log($"Deleted: {key}"); + } + } + } +} diff --git a/Assets/Editor/SetIcosaToken.cs.meta b/Assets/Editor/SetIcosaToken.cs.meta new file mode 100644 index 0000000000..eff53debf6 --- /dev/null +++ b/Assets/Editor/SetIcosaToken.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 5918c754a3d344139ef0469bc3e3fbce +timeCreated: 1720622791 \ No newline at end of file diff --git a/Assets/Editor/Tests/TestVrAssetService.cs b/Assets/Editor/Tests/TestVrAssetService.cs index e5ceade4da..d432de63ce 100644 --- a/Assets/Editor/Tests/TestVrAssetService.cs +++ b/Assets/Editor/Tests/TestVrAssetService.cs @@ -131,7 +131,7 @@ public void RunAfterAllTests() public void TestConvertFruToPoly() { // Test that the basis-conversion transforms seem correct - var zFromU = VrAssetService.kPolyFromUnity; + var zFromU = VrAssetService.kIcosaFromUnity; var uFromZ = zFromU.inverse; Assert.AreEqual(kZForward, zFromU * Vector3.forward); Assert.AreEqual(kZRight, zFromU * Vector3.right); @@ -145,7 +145,7 @@ public void TestConvertFruToPoly() public void TestTransformByForBasisChange() { // This is more a test of TrTransform.TransformBy than anything else - var zFromU = VrAssetService.kPolyFromUnity; + var zFromU = VrAssetService.kIcosaFromUnity; // This rotates Unity-forward to Unity-right TrTransform xfFwdToRt_U = TrTransform.R(Quaternion.AngleAxis(90, Vector3.up)); diff --git a/Assets/Materials/IcosaIcon.mat b/Assets/Materials/IcosaIcon.mat new file mode 100644 index 0000000000..df7907bd0e --- /dev/null +++ b/Assets/Materials/IcosaIcon.mat @@ -0,0 +1,81 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 8 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: IcosaIcon + m_Shader: {fileID: 4800000, guid: e9594cae8deb0e44ba4c46191f40b4f9, type: 3} + m_ValidKeywords: [] + m_InvalidKeywords: + - _EMISSION + m_LightmapFlags: 1 + 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: ca2b2689a21743448be1a5306c61e90b, 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_Ints: [] + m_Floats: + - _BumpScale: 1 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _GlossMapScale: 1 + - _Glossiness: 0.5 + - _GlossyReflections: 1 + - _Metallic: 0 + - _Mode: 0 + - _OcclusionStrength: 1 + - _Parallax: 0.02 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _UVSec: 0 + - _ZWrite: 1 + m_Colors: + - _Color: {r: 1, g: 1, b: 1, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} + m_BuildTextureStacks: [] diff --git a/Assets/Materials/IcosaIcon.mat.meta b/Assets/Materials/IcosaIcon.mat.meta new file mode 100644 index 0000000000..e0d5d451e5 --- /dev/null +++ b/Assets/Materials/IcosaIcon.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e7a4b5a3979042447af7f344f59498c7 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Prefabs/GltfExportStandinManager.prefab b/Assets/Prefabs/GltfExportStandinManager.prefab new file mode 100644 index 0000000000..c213b88970 --- /dev/null +++ b/Assets/Prefabs/GltfExportStandinManager.prefab @@ -0,0 +1,131 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &5512400623774099615 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2455894836569734632} + - component: {fileID: 7950399880331140669} + m_Layer: 0 + m_Name: GltfExportStandinManager + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &2455894836569734632 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5512400623774099615} + 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_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 6935990006228621101} + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &7950399880331140669 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5512400623774099615} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 14919aff2e114a19b65a5e58509e1d81, type: 3} + m_Name: + m_EditorClassIdentifier: + m_TemporarySkySphere: {fileID: 6935990006228621101} +--- !u!1001 &6935990006228749741 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + m_TransformParent: {fileID: 2455894836569734632} + m_Modifications: + - target: {fileID: 100000, guid: 9c85be13d3f1fd84f94cc7551c16c7cd, type: 3} + propertyPath: m_Name + value: InvertedSphere + objectReference: {fileID: 0} + - target: {fileID: 100000, guid: 9c85be13d3f1fd84f94cc7551c16c7cd, type: 3} + propertyPath: m_IsActive + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 400000, guid: 9c85be13d3f1fd84f94cc7551c16c7cd, type: 3} + propertyPath: m_RootOrder + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 400000, guid: 9c85be13d3f1fd84f94cc7551c16c7cd, type: 3} + propertyPath: m_LocalScale.x + value: 100 + objectReference: {fileID: 0} + - target: {fileID: 400000, guid: 9c85be13d3f1fd84f94cc7551c16c7cd, type: 3} + propertyPath: m_LocalScale.y + value: 100 + objectReference: {fileID: 0} + - target: {fileID: 400000, guid: 9c85be13d3f1fd84f94cc7551c16c7cd, type: 3} + propertyPath: m_LocalScale.z + value: 100 + objectReference: {fileID: 0} + - target: {fileID: 400000, guid: 9c85be13d3f1fd84f94cc7551c16c7cd, type: 3} + propertyPath: m_LocalPosition.x + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 400000, guid: 9c85be13d3f1fd84f94cc7551c16c7cd, type: 3} + propertyPath: m_LocalPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 400000, guid: 9c85be13d3f1fd84f94cc7551c16c7cd, type: 3} + propertyPath: m_LocalPosition.z + value: 0.03281074 + objectReference: {fileID: 0} + - target: {fileID: 400000, guid: 9c85be13d3f1fd84f94cc7551c16c7cd, type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 400000, guid: 9c85be13d3f1fd84f94cc7551c16c7cd, type: 3} + propertyPath: m_LocalRotation.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 400000, guid: 9c85be13d3f1fd84f94cc7551c16c7cd, type: 3} + propertyPath: m_LocalRotation.y + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 400000, guid: 9c85be13d3f1fd84f94cc7551c16c7cd, type: 3} + propertyPath: m_LocalRotation.z + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 400000, guid: 9c85be13d3f1fd84f94cc7551c16c7cd, type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 400000, guid: 9c85be13d3f1fd84f94cc7551c16c7cd, type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 400000, guid: 9c85be13d3f1fd84f94cc7551c16c7cd, type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2300000, guid: 9c85be13d3f1fd84f94cc7551c16c7cd, type: 3} + propertyPath: m_Materials.Array.data[0] + value: + objectReference: {fileID: 2100000, guid: 77b09cb82a5ffa94fb37bccf98d2fc84, type: 2} + m_RemovedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: 9c85be13d3f1fd84f94cc7551c16c7cd, type: 3} +--- !u!4 &6935990006228621101 stripped +Transform: + m_CorrespondingSourceObject: {fileID: 400000, guid: 9c85be13d3f1fd84f94cc7551c16c7cd, + type: 3} + m_PrefabInstance: {fileID: 6935990006228749741} + m_PrefabAsset: {fileID: 0} diff --git a/Assets/Prefabs/GltfExportStandinManager.prefab.meta b/Assets/Prefabs/GltfExportStandinManager.prefab.meta new file mode 100644 index 0000000000..a9848cdc60 --- /dev/null +++ b/Assets/Prefabs/GltfExportStandinManager.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: fd97be770c9e84eb1b5fcc5c06bd0adf +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Prefabs/Keyboard/Keyboard.prefab b/Assets/Prefabs/Keyboard/Keyboard.prefab index 1211bfe519..3c834731d5 100644 --- a/Assets/Prefabs/Keyboard/Keyboard.prefab +++ b/Assets/Prefabs/Keyboard/Keyboard.prefab @@ -973,6 +973,11 @@ PrefabInstance: propertyPath: _layout value: 0 objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 33 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _printShift @@ -1177,6 +1182,11 @@ PrefabInstance: propertyPath: m_Text value: objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 42 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _printShift @@ -1386,6 +1396,11 @@ PrefabInstance: propertyPath: m_Text value: objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 8 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _printShift @@ -1600,6 +1615,11 @@ PrefabInstance: propertyPath: _keyType value: 3 objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 72 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _printShift @@ -1839,6 +1859,11 @@ PrefabInstance: propertyPath: m_Text value: objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 45 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _printShift @@ -2058,6 +2083,11 @@ PrefabInstance: propertyPath: _keyType value: 1 objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 3 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _printShift @@ -2282,6 +2312,11 @@ PrefabInstance: propertyPath: _layout value: 0 objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 24 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _printShift @@ -2496,6 +2531,11 @@ PrefabInstance: propertyPath: _layout value: 0 objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 17 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _printShift @@ -2710,6 +2750,11 @@ PrefabInstance: propertyPath: _layout value: 0 objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 32 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _printShift @@ -2919,6 +2964,11 @@ PrefabInstance: propertyPath: _layout value: 0 objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 39 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _printShift @@ -3138,6 +3188,11 @@ PrefabInstance: propertyPath: _keyType value: 8 objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 65 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _printShift @@ -3377,6 +3432,11 @@ PrefabInstance: propertyPath: _layout value: 0 objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 36 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _printShift @@ -3591,6 +3651,11 @@ PrefabInstance: propertyPath: _layout value: 0 objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 18 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _printShift @@ -3800,6 +3865,11 @@ PrefabInstance: propertyPath: m_Text value: objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 47 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _printShift @@ -4014,6 +4084,11 @@ PrefabInstance: propertyPath: _layout value: 0 objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 23 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _printShift @@ -4223,6 +4298,11 @@ PrefabInstance: propertyPath: m_Text value: objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 7 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _printShift @@ -4432,6 +4512,11 @@ PrefabInstance: propertyPath: m_Text value: objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 14 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _printShift @@ -4646,6 +4731,11 @@ PrefabInstance: propertyPath: _layout value: 0 objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 31 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _printShift @@ -4860,6 +4950,11 @@ PrefabInstance: propertyPath: _layout value: 0 objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 15 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _printShift @@ -5074,6 +5169,11 @@ PrefabInstance: propertyPath: _layout value: 0 objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 35 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _printShift @@ -5293,6 +5393,11 @@ PrefabInstance: propertyPath: _keyType value: 6 objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 54 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _printShift @@ -5532,6 +5637,11 @@ PrefabInstance: propertyPath: _layout value: 0 objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 29 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _printShift @@ -5746,6 +5856,11 @@ PrefabInstance: propertyPath: _layout value: 0 objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 28 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _printShift @@ -5960,6 +6075,11 @@ PrefabInstance: propertyPath: _layout value: 0 objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 21 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _printShift @@ -6174,6 +6294,11 @@ PrefabInstance: propertyPath: _layout value: 0 objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 38 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _printShift @@ -6383,6 +6508,11 @@ PrefabInstance: propertyPath: m_Text value: objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 13 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _printShift @@ -6602,6 +6732,11 @@ PrefabInstance: propertyPath: _keyType value: 4 objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 55 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _printShift @@ -6841,6 +6976,11 @@ PrefabInstance: propertyPath: _layout value: 0 objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 20 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _printShift @@ -7055,6 +7195,11 @@ PrefabInstance: propertyPath: _layout value: 0 objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 40 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _printShift @@ -7264,6 +7409,11 @@ PrefabInstance: propertyPath: m_Text value: objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 10 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _printShift @@ -7473,6 +7623,11 @@ PrefabInstance: propertyPath: m_Text value: objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 12 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _printShift @@ -7687,6 +7842,11 @@ PrefabInstance: propertyPath: _layout value: 0 objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 26 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _printShift @@ -7896,6 +8056,11 @@ PrefabInstance: propertyPath: m_Text value: objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 41 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _printShift @@ -8110,6 +8275,11 @@ PrefabInstance: propertyPath: _layout value: 0 objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 25 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _printShift @@ -8319,6 +8489,11 @@ PrefabInstance: propertyPath: m_Text value: objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 11 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _printShift @@ -8528,6 +8703,11 @@ PrefabInstance: propertyPath: m_Text value: objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 50 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _printShift @@ -8737,6 +8917,11 @@ PrefabInstance: propertyPath: m_Text value: objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 43 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _printShift @@ -8956,6 +9141,11 @@ PrefabInstance: propertyPath: _keyType value: 4 objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 56 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _printShift @@ -9195,6 +9385,11 @@ PrefabInstance: propertyPath: _layout value: 0 objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 19 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _printShift @@ -9409,6 +9604,11 @@ PrefabInstance: propertyPath: _layout value: 0 objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 22 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _printShift @@ -9618,6 +9818,11 @@ PrefabInstance: propertyPath: m_Text value: objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 4 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _controlInput @@ -9817,6 +10022,11 @@ PrefabInstance: propertyPath: _keyType value: 2 objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 51 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _printShift @@ -10051,6 +10261,11 @@ PrefabInstance: propertyPath: m_Text value: objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 5 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _printShift @@ -10265,6 +10480,11 @@ PrefabInstance: propertyPath: _layout value: 0 objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 27 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _printShift @@ -10474,6 +10694,11 @@ PrefabInstance: propertyPath: m_Text value: objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 6 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _printShift @@ -10683,6 +10908,11 @@ PrefabInstance: propertyPath: m_Text value: objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 49 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _printShift @@ -10902,6 +11132,11 @@ PrefabInstance: propertyPath: _keyType value: 2 objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 52 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _printShift @@ -11136,6 +11371,11 @@ PrefabInstance: propertyPath: m_Text value: objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 48 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _printShift @@ -11350,6 +11590,11 @@ PrefabInstance: propertyPath: _layout value: 0 objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 30 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _printShift @@ -11564,6 +11809,11 @@ PrefabInstance: propertyPath: m_Text value: objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 44 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _printShift @@ -11773,6 +12023,11 @@ PrefabInstance: propertyPath: m_Text value: objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 9 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _printShift @@ -11992,6 +12247,11 @@ PrefabInstance: propertyPath: _keyType value: 7 objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 2 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _printShift @@ -12231,6 +12491,11 @@ PrefabInstance: propertyPath: _layout value: 0 objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 37 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _printShift @@ -12445,6 +12710,11 @@ PrefabInstance: propertyPath: _layout value: 0 objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 34 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _printShift @@ -12654,6 +12924,11 @@ PrefabInstance: propertyPath: m_Text value: objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 46 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _printShift @@ -12868,6 +13143,11 @@ PrefabInstance: propertyPath: _layout value: 0 objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 1 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _printShift @@ -13122,6 +13402,11 @@ PrefabInstance: propertyPath: _layout value: 0 objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 16 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _printShift @@ -13341,6 +13626,11 @@ PrefabInstance: propertyPath: _keyType value: 5 objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 53 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _printShift diff --git a/Assets/Prefabs/Keyboard/NumericKeyboard.prefab b/Assets/Prefabs/Keyboard/NumericKeyboard.prefab index 2e022cf95a..aff3fcba29 100644 --- a/Assets/Prefabs/Keyboard/NumericKeyboard.prefab +++ b/Assets/Prefabs/Keyboard/NumericKeyboard.prefab @@ -365,6 +365,11 @@ PrefabInstance: propertyPath: _layout value: 0 objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 13 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _forceLabel @@ -609,6 +614,11 @@ PrefabInstance: propertyPath: _layout value: 0 objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 42 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _forceLabel @@ -838,6 +848,11 @@ PrefabInstance: propertyPath: _layout value: 0 objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 45 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _forceLabel @@ -1072,6 +1087,11 @@ PrefabInstance: propertyPath: _keyType value: 8 objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 65 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _forceLabel @@ -1326,6 +1346,11 @@ PrefabInstance: propertyPath: _layout value: 0 objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 47 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _forceLabel @@ -1555,6 +1580,11 @@ PrefabInstance: propertyPath: _layout value: 0 objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 7 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _forceLabel @@ -1784,6 +1814,11 @@ PrefabInstance: propertyPath: _layout value: 0 objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 8 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _forceLabel @@ -2013,6 +2048,11 @@ PrefabInstance: propertyPath: _layout value: 0 objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 41 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _forceLabel @@ -2242,6 +2282,11 @@ PrefabInstance: propertyPath: _layout value: 0 objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 50 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _forceLabel @@ -2471,6 +2516,11 @@ PrefabInstance: propertyPath: _layout value: 0 objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 43 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _forceLabel @@ -2700,6 +2750,11 @@ PrefabInstance: propertyPath: _layout value: 0 objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 49 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _forceLabel @@ -2929,6 +2984,11 @@ PrefabInstance: propertyPath: _layout value: 0 objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 48 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _forceLabel @@ -3163,6 +3223,11 @@ PrefabInstance: propertyPath: _layout value: 0 objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 44 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _forceLabel @@ -3397,6 +3462,11 @@ PrefabInstance: propertyPath: _keyType value: 7 objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 2 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _forceLabel @@ -3651,6 +3721,11 @@ PrefabInstance: propertyPath: _layout value: 0 objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 46 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _forceLabel @@ -3880,6 +3955,11 @@ PrefabInstance: propertyPath: _layout value: 0 objectReference: {fileID: 0} + - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, + type: 3} + propertyPath: _keycode + value: 1 + objectReference: {fileID: 0} - target: {fileID: 114586615171430532, guid: 6037d0909c862e84a89c912556ca9aaf, type: 3} propertyPath: _forceLabel diff --git a/Assets/Prefabs/Panels/PolyPanel.prefab b/Assets/Prefabs/Panels/IcosaPanel.prefab similarity index 97% rename from Assets/Prefabs/Panels/PolyPanel.prefab rename to Assets/Prefabs/Panels/IcosaPanel.prefab index e639dd7116..d172bc1a18 100644 --- a/Assets/Prefabs/Panels/PolyPanel.prefab +++ b/Assets/Prefabs/Panels/IcosaPanel.prefab @@ -27,13 +27,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 106270} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0.666, y: -0.927, z: 0.05} m_LocalScale: {x: 0.27, y: 0.27, z: 0.27} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 465812} - m_RootOrder: 11 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &3345126 MeshFilter: @@ -93,9 +93,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 106270} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1, y: 1, z: 0.01} m_Center: {x: 0, y: 0, z: 0} --- !u!114 &11464876 @@ -164,7 +172,7 @@ GameObject: - component: {fileID: 11474066} - component: {fileID: 114370098467888466} m_Layer: 16 - m_Name: PolyPanel + m_Name: IcosaPanel m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 @@ -177,6 +185,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 141494} + serializedVersion: 2 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} @@ -186,7 +195,6 @@ Transform: - {fileID: 4000011255173414} - {fileID: 465812} m_Father: {fileID: 0} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!114 &114000010862122888 MonoBehaviour: @@ -259,12 +267,12 @@ MonoBehaviour: m_ClampToBounds: 1 m_ReticleBounds: {x: 2.55, y: 2.35, z: 0} m_BorderSphereHighlightRadius: 2.5 - m_PositioningSpheresBounds: {x: 1, y: 0} + m_PositioningSpheresBounds: {x: 1, y: 1} m_PositioningSphereRadius: 0.4 m_UseGazeRotation: 1 m_MaxGazeRotation: 20 m_GazeActivateSpeed: 8 - m_InitialSpawnPos: {x: 0, y: 0, z: 0} + m_InitialSpawnPos: {x: -7, y: 15, z: 6} m_InitialSpawnRotEulers: {x: 0, y: 0, z: 0} m_WandAttachAngle: 0 m_WandAttachYOffset: 0 @@ -391,13 +399,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 146636} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0.1} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 465812} - m_RootOrder: 4 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &3338058 MeshFilter: @@ -430,6 +438,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 167476} + serializedVersion: 2 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} @@ -463,7 +472,6 @@ Transform: - {fileID: 4000013357198230} - {fileID: 1728879999287929109} m_Father: {fileID: 471112} - m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &170558 GameObject: @@ -489,13 +497,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 170558} + serializedVersion: 2 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_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 471112} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!65 &6578658 BoxCollider: @@ -505,9 +513,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 170558} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 2.3084, y: 2.8000002, z: 0.5} m_Center: {x: 0, y: 0, z: 0} --- !u!1 &177738 @@ -534,13 +550,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 177738} + serializedVersion: 2 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_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 465812} - m_RootOrder: 9 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!65 &6508354 BoxCollider: @@ -550,9 +566,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 177738} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1.8083999, y: 2.3000002, z: 0.02} m_Center: {x: 0, y: 0, z: 0} --- !u!1 &199414 @@ -582,13 +606,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 199414} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: -0.247, y: -0.927, z: 0.05} m_LocalScale: {x: 0.27, y: 0.27, z: 0.27} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 465812} - m_RootOrder: 10 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &3323192 MeshFilter: @@ -648,9 +672,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 199414} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1, y: 1, z: 0.01} m_Center: {x: 0, y: 0, z: 0} --- !u!114 &11463628 @@ -733,6 +765,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000010087135480} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0.627, y: -0.108, z: 0.08} m_LocalScale: {x: 0.35, y: 0.35, z: 0.35} @@ -740,7 +773,6 @@ Transform: m_Children: - {fileID: 4000012374902596} m_Father: {fileID: 465812} - m_RootOrder: 15 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000010907512276 MeshFilter: @@ -800,9 +832,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000010087135480} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1.0000001, y: 1.0000001, z: 0.025} m_Center: {x: 0, y: 0, z: 0} --- !u!114 &114000010337963734 @@ -856,7 +896,15 @@ MonoBehaviour: m_UnloadedTexture: {fileID: 2800000, guid: 92139e46e58d3924fb8e16ba42a0145f, type: 3} m_LoadedTexture: {fileID: 2800000, guid: e9a34c5f95833b248b106d4f7d83d9ad, type: 3} m_ErrorTexture: {fileID: 2800000, guid: 0c91e975bed1cd948a150b672f3fec48, type: 3} - m_LoadHelpText: Click to Load + m_LoadHelpText: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] m_LoadingOverlay: {fileID: 1000011887412796} references: version: 2 @@ -886,13 +934,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000010298050724} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: -0.01} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000010071936162} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000011346989110 MeshFilter: @@ -969,13 +1017,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000010313941914} + serializedVersion: 2 m_LocalRotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071067} m_LocalPosition: {x: -0, y: 0, z: 0} m_LocalScale: {x: 100, y: 100, z: 100} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000012902286828} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000011347804352 MeshFilter: @@ -1050,13 +1098,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000010339999408} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 0, y: 0, z: 0} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000013774678408} - m_RootOrder: 5 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &1000010474425972 GameObject: @@ -1083,13 +1131,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000010474425972} + serializedVersion: 2 m_LocalRotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071067} m_LocalPosition: {x: -0, y: 0, z: 0} m_LocalScale: {x: 100, y: 100, z: 100} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000012676471016} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000012427647034 MeshFilter: @@ -1166,13 +1214,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000010592129534} + serializedVersion: 2 m_LocalRotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071067} m_LocalPosition: {x: -0, y: 0, z: 0} m_LocalScale: {x: 100, y: 100, z: 100} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000010583109832} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000013295006944 MeshFilter: @@ -1250,13 +1298,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000010887400618} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0.129, y: 0.3911, z: -0.041999996} m_LocalScale: {x: 0.17, y: 0.17, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000010258256146} - m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000010323384624 MeshFilter: @@ -1274,9 +1322,17 @@ MeshCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000010887400618} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 4 + serializedVersion: 5 m_Convex: 0 m_CookingOptions: 30 m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} @@ -1346,6 +1402,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000010933935756} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: -0.1, z: -0.05} m_LocalScale: {x: 1, y: 1, z: 1} @@ -1354,7 +1411,6 @@ Transform: - {fileID: 2631587096066588542} - {fileID: 4000010274953216} m_Father: {fileID: 465812} - m_RootOrder: 25 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!23 &23000011207303254 MeshRenderer: @@ -1421,13 +1477,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000010957668132} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 0, y: 0, z: 0} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000013774678408} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &1000010961947472 GameObject: @@ -1455,13 +1511,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000010961947472} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0.05999999} m_LocalScale: {x: 2, y: 1, z: 0.8783332} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000013940156938} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000011003021764 MeshFilter: @@ -1479,9 +1535,17 @@ MeshCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000010961947472} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 4 + serializedVersion: 5 m_Convex: 0 m_CookingOptions: 30 m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} @@ -1552,13 +1616,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000011102024434} + serializedVersion: 2 m_LocalRotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071067} m_LocalPosition: {x: -0, y: 0, z: 0} m_LocalScale: {x: 100, y: 100, z: 100} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000013851072734} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000012816624386 MeshFilter: @@ -1636,13 +1700,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000011118790432} + serializedVersion: 2 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_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 465812} - m_RootOrder: 8 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000011393229142 MeshFilter: @@ -1734,6 +1798,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000011266074316} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0.207, y: -0.525, z: 0.08} m_LocalScale: {x: 0.35, y: 0.35, z: 0.35} @@ -1741,7 +1806,6 @@ Transform: m_Children: - {fileID: 4000010573672924} m_Father: {fileID: 465812} - m_RootOrder: 17 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000012808144226 MeshFilter: @@ -1801,9 +1865,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000011266074316} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1.0000001, y: 1.0000001, z: 0.025} m_Center: {x: 0, y: 0, z: 0} --- !u!114 &114000013156484394 @@ -1857,7 +1929,15 @@ MonoBehaviour: m_UnloadedTexture: {fileID: 2800000, guid: 92139e46e58d3924fb8e16ba42a0145f, type: 3} m_LoadedTexture: {fileID: 2800000, guid: e9a34c5f95833b248b106d4f7d83d9ad, type: 3} m_ErrorTexture: {fileID: 2800000, guid: 0c91e975bed1cd948a150b672f3fec48, type: 3} - m_LoadHelpText: Click to Load + m_LoadHelpText: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] m_LoadingOverlay: {fileID: 1000012134891236} references: version: 2 @@ -1885,13 +1965,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000011318793836} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 0, y: 0, z: 0} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000013774678408} - m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &1000011418975696 GameObject: @@ -1920,6 +2000,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000011418975696} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0.627, y: -0.525, z: 0.08} m_LocalScale: {x: 0.35, y: 0.35, z: 0.35} @@ -1927,7 +2008,6 @@ Transform: m_Children: - {fileID: 4000012573971770} m_Father: {fileID: 465812} - m_RootOrder: 18 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000010171189952 MeshFilter: @@ -1987,9 +2067,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000011418975696} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1.0000001, y: 1.0000001, z: 0.025} m_Center: {x: 0, y: 0, z: 0} --- !u!114 &114000010451906298 @@ -2043,7 +2131,15 @@ MonoBehaviour: m_UnloadedTexture: {fileID: 2800000, guid: 92139e46e58d3924fb8e16ba42a0145f, type: 3} m_LoadedTexture: {fileID: 2800000, guid: e9a34c5f95833b248b106d4f7d83d9ad, type: 3} m_ErrorTexture: {fileID: 2800000, guid: 0c91e975bed1cd948a150b672f3fec48, type: 3} - m_LoadHelpText: Click to Load + m_LoadHelpText: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] m_LoadingOverlay: {fileID: 1000014145540092} references: version: 2 @@ -2073,13 +2169,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000011603093424} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: -0.68239236, y: 0.002720356, z: 0.014} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 465812} - m_RootOrder: 19 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000012418862958 MeshFilter: @@ -2158,13 +2254,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000011686355436} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: -0.693, y: 0.942, z: 0} m_LocalScale: {x: 0.27, y: 0.27, z: 0.27} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 465812} - m_RootOrder: 3 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000011749087192 MeshFilter: @@ -2224,9 +2320,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000011686355436} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1, y: 1, z: 0.1} m_Center: {x: 0, y: 0, z: 0} --- !u!114 &114000011188303058 @@ -2265,7 +2369,7 @@ MonoBehaviour: m_LocalVariables: [] m_DescriptionActivateSpeed: 12 m_DescriptionZScale: 1 - m_ButtonTexture: {fileID: 2800000, guid: da8fcd82368826b4cad505e8249bd63c, type: 3} + m_ButtonTexture: {fileID: 2800000, guid: ca2b2689a21743448be1a5306c61e90b, type: 3} m_AtlasTexture: 1 m_ToggleButton: 0 m_LongPressReleaseButton: 0 @@ -2334,6 +2438,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000011746198504} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0.209, y: -0.406, z: -0.054} m_LocalScale: {x: 0.29999998, y: 0.29999998, z: 0.29999998} @@ -2342,7 +2447,6 @@ Transform: - {fileID: 2459190327082045982} - {fileID: 4000012173239436} m_Father: {fileID: 4000014190517824} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000012570074730 MeshFilter: @@ -2402,9 +2506,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000011746198504} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 2, y: 1, z: 0.01} m_Center: {x: 0, y: 0, z: 0} --- !u!114 &114000013674408190 @@ -2512,6 +2624,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000011782189388} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0.21, y: -0.406, z: -0.054000005} m_LocalScale: {x: 0.29999998, y: 0.29999998, z: 0.29999998} @@ -2520,7 +2633,6 @@ Transform: - {fileID: 2001505504518591488} - {fileID: 4000011038848668} m_Father: {fileID: 4000010713138772} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000010848474370 MeshFilter: @@ -2658,9 +2770,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000011782189388} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 2, y: 1.0000001, z: 0.1} m_Center: {x: 0, y: 0, z: 0} --- !u!1 &1000011854602082 @@ -2686,6 +2806,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000011854602082} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0.209, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} @@ -2694,7 +2815,6 @@ Transform: - {fileID: 4000014150265184} - {fileID: 4000011110165888} m_Father: {fileID: 4000010185127306} - m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &1000011887412796 GameObject: @@ -2721,13 +2841,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000011887412796} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: -0.01} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000012505868838} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000012418927610 MeshFilter: @@ -2804,13 +2924,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000011916187790} + serializedVersion: 2 m_LocalRotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071067} m_LocalPosition: {x: -0, y: 0, z: 0} m_LocalScale: {x: 100, y: 100, z: 100} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000012676471016} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000012203188556 MeshFilter: @@ -2885,6 +3005,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000011934193470} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0.209, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} @@ -2893,7 +3014,6 @@ Transform: - {fileID: 4000010681971296} - {fileID: 4000013032411082} m_Father: {fileID: 4000013357198230} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &1000011998859986 GameObject: @@ -2919,6 +3039,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000011998859986} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: -0.1, z: -0.05} m_LocalScale: {x: 1, y: 1, z: 1} @@ -2928,7 +3049,6 @@ Transform: - {fileID: 4000013940156938} - {fileID: 4000010583109832} m_Father: {fileID: 465812} - m_RootOrder: 24 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!23 &23000010342337010 MeshRenderer: @@ -2999,6 +3119,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000012065099252} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: -0.206, y: -0.525, z: 0.08} m_LocalScale: {x: 0.35, y: 0.35, z: 0.35} @@ -3006,7 +3127,6 @@ Transform: m_Children: - {fileID: 4000011549167550} m_Father: {fileID: 465812} - m_RootOrder: 16 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000010156527234 MeshFilter: @@ -3066,9 +3186,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000012065099252} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1.0000001, y: 1.0000001, z: 0.025} m_Center: {x: 0, y: 0, z: 0} --- !u!114 &114000013205858318 @@ -3122,7 +3250,15 @@ MonoBehaviour: m_UnloadedTexture: {fileID: 2800000, guid: 92139e46e58d3924fb8e16ba42a0145f, type: 3} m_LoadedTexture: {fileID: 2800000, guid: e9a34c5f95833b248b106d4f7d83d9ad, type: 3} m_ErrorTexture: {fileID: 2800000, guid: 0c91e975bed1cd948a150b672f3fec48, type: 3} - m_LoadHelpText: Click to Load + m_LoadHelpText: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] m_LoadingOverlay: {fileID: 1000010298050724} references: version: 2 @@ -3154,13 +3290,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000012109970132} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: -0.68226534, y: 0.289, z: 0.003} m_LocalScale: {x: 0.393, y: 0.395, z: 0.395} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 465812} - m_RootOrder: 5 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000014007660200 MeshFilter: @@ -3270,9 +3406,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000012109970132} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1.1, y: 0.8, z: 0.025} m_Center: {x: 0, y: 0, z: 0} --- !u!1 &1000012134891236 @@ -3300,13 +3444,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000012134891236} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: -0, z: -0.01} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000013437124302} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000012148575110 MeshFilter: @@ -3383,13 +3527,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000012156671066} + serializedVersion: 2 m_LocalRotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071067} m_LocalPosition: {x: -0, y: 0, z: 0} m_LocalScale: {x: 100, y: 100, z: 100} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000010274953216} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000013878566190 MeshFilter: @@ -3464,6 +3608,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000012254481722} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0.209, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} @@ -3472,7 +3617,6 @@ Transform: - {fileID: 4000012695734804} - {fileID: 4000011402503074} m_Father: {fileID: 4000014190517824} - m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &1000012257498920 GameObject: @@ -3498,6 +3642,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000012257498920} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: -0.1, z: -0.05} m_LocalScale: {x: 1, y: 1, z: 1} @@ -3508,7 +3653,6 @@ Transform: - {fileID: 4000013275467134} - {fileID: 4000013851072734} m_Father: {fileID: 465812} - m_RootOrder: 22 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!23 &23000013438199350 MeshRenderer: @@ -3577,13 +3721,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000012433234120} + serializedVersion: 2 m_LocalRotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071067} m_LocalPosition: {x: -0, y: 0, z: 0} m_LocalScale: {x: 100, y: 100, z: 100} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000013851072734} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000011902349082 MeshFilter: @@ -3658,6 +3802,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000012535319180} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0.209, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} @@ -3666,7 +3811,6 @@ Transform: - {fileID: 4000013572391784} - {fileID: 4000010847277736} m_Father: {fileID: 4000010713138772} - m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &1000012632648426 GameObject: @@ -3693,13 +3837,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000012632648426} + serializedVersion: 2 m_LocalRotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071067} m_LocalPosition: {x: -0, y: 0, z: 0} m_LocalScale: {x: 100, y: 100, z: 100} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000010583109832} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000010560099168 MeshFilter: @@ -3777,13 +3921,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000012648007250} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0.05999999} m_LocalScale: {x: 2, y: 1, z: 0.8783332} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000012309134638} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000011299344062 MeshFilter: @@ -3801,9 +3945,17 @@ MeshCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000012648007250} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 4 + serializedVersion: 5 m_Convex: 0 m_CookingOptions: 30 m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} @@ -3873,6 +4025,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000012677157260} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: -0.1, z: -0.05} m_LocalScale: {x: 1, y: 1, z: 1} @@ -3882,7 +4035,6 @@ Transform: - {fileID: 4000012135202400} - {fileID: 4000012676471016} m_Father: {fileID: 465812} - m_RootOrder: 23 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!23 &23000013656731088 MeshRenderer: @@ -3951,13 +4103,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000012700630038} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 2, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000012135202400} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000010348517304 MeshFilter: @@ -4036,6 +4188,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000012840250180} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0.209, y: -0.406, z: -0.054000005} m_LocalScale: {x: 0.29999998, y: 0.29999998, z: 0.29999998} @@ -4044,7 +4197,6 @@ Transform: - {fileID: 944172704919589472} - {fileID: 4000010958123902} m_Father: {fileID: 4000010185127306} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000011317273212 MeshFilter: @@ -4104,9 +4256,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000012840250180} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 2, y: 1, z: 0.01} m_Center: {x: 0, y: 0, z: 0} --- !u!114 &114000012803435128 @@ -4211,6 +4371,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000012895512256} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: -0.1, z: -0.05} m_LocalScale: {x: 1, y: 1, z: 1} @@ -4220,7 +4381,6 @@ Transform: - {fileID: 4000010287137376} - {fileID: 4000012902286828} m_Father: {fileID: 465812} - m_RootOrder: 20 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!23 &23000013360289746 MeshRenderer: @@ -4291,6 +4451,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000013033931112} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: -0.206, y: -0.108, z: 0.08} m_LocalScale: {x: 0.35, y: 0.35, z: 0.35} @@ -4298,7 +4459,6 @@ Transform: m_Children: - {fileID: 4000012934970154} m_Father: {fileID: 465812} - m_RootOrder: 13 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000010877679830 MeshFilter: @@ -4358,9 +4518,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000013033931112} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1.0000001, y: 1.0000001, z: 0.025} m_Center: {x: 0, y: 0, z: 0} --- !u!114 &114000012757722782 @@ -4414,7 +4582,15 @@ MonoBehaviour: m_UnloadedTexture: {fileID: 2800000, guid: 92139e46e58d3924fb8e16ba42a0145f, type: 3} m_LoadedTexture: {fileID: 2800000, guid: e9a34c5f95833b248b106d4f7d83d9ad, type: 3} m_ErrorTexture: {fileID: 2800000, guid: 0c91e975bed1cd948a150b672f3fec48, type: 3} - m_LoadHelpText: Click to Load + m_LoadHelpText: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] m_LoadingOverlay: {fileID: 1000014019108166} references: version: 2 @@ -4442,6 +4618,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000013045178456} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0.2, y: 0.44, z: 0.08} m_LocalScale: {x: 0.59999996, y: 0.59999996, z: 0.59999996} @@ -4454,7 +4631,6 @@ Transform: - {fileID: 4000012973175376} - {fileID: 4000011998283800} m_Father: {fileID: 465812} - m_RootOrder: 12 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &1000013164525870 GameObject: @@ -4479,6 +4655,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000013164525870} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0.209, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} @@ -4487,7 +4664,6 @@ Transform: - {fileID: 4000014152566328} - {fileID: 4000012457610374} m_Father: {fileID: 4000010258256146} - m_RootOrder: 3 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &1000013194522416 GameObject: @@ -4514,13 +4690,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000013194522416} + serializedVersion: 2 m_LocalRotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071067} m_LocalPosition: {x: -0, y: 0, z: 0} m_LocalScale: {x: 100, y: 100, z: 100} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000012902286828} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000014091131168 MeshFilter: @@ -4595,13 +4771,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000013227438200} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 0, y: 0, z: 0} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000013774678408} - m_RootOrder: 4 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &1000013244881560 GameObject: @@ -4626,13 +4802,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000013244881560} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 0, y: 0, z: 0} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000013774678408} - m_RootOrder: 3 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &1000013669222526 GameObject: @@ -4659,13 +4835,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000013669222526} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1.9083999, y: 2.4674253, z: 2.158998} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 471112} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000012204931114 MeshFilter: @@ -4744,13 +4920,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000013717588074} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: -0.68226534, y: 0, z: 0.003} m_LocalScale: {x: 0.393, y: 0.393, z: 0.393} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 465812} - m_RootOrder: 6 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000010703057562 MeshFilter: @@ -4810,9 +4986,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000013717588074} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1.1, y: 0.8, z: 0.025} m_Center: {x: 0, y: 0, z: 0} --- !u!114 &114020894668800226 @@ -4888,13 +5072,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000013727554954} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 0, y: 0, z: 0} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000013774678408} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &1000013820106702 GameObject: @@ -4923,13 +5107,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000013820106702} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: -0.68226534, y: -0.287, z: 0.003} m_LocalScale: {x: 0.393, y: 0.393, z: 0.393} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 465812} - m_RootOrder: 7 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000012084355200 MeshFilter: @@ -5039,9 +5223,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000013820106702} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1.1, y: 0.8, z: 0.025} m_Center: {x: 0, y: 0, z: 0} --- !u!1 &1000013864904278 @@ -5069,13 +5261,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000013864904278} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: -0.01} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000010375171238} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000011183412372 MeshFilter: @@ -5153,13 +5345,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000013965171982} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0.05999999} m_LocalScale: {x: 2, y: 1, z: 0.8783332} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000010287137376} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000013560793154 MeshFilter: @@ -5177,9 +5369,17 @@ MeshCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000013965171982} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 4 + serializedVersion: 5 m_Convex: 0 m_CookingOptions: 30 m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} @@ -5250,13 +5450,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000014019108166} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: -0.01} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000012918810746} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000012744993406 MeshFilter: @@ -5333,13 +5533,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000014078913134} + serializedVersion: 2 m_LocalRotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071067} m_LocalPosition: {x: -0, y: 0, z: 0} m_LocalScale: {x: 100, y: 100, z: 100} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000010274953216} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000011738738920 MeshFilter: @@ -5418,6 +5618,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000014142736920} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0.207, y: -0.108, z: 0.08} m_LocalScale: {x: 0.35, y: 0.35, z: 0.35} @@ -5425,7 +5626,6 @@ Transform: m_Children: - {fileID: 4000011362327722} m_Father: {fileID: 465812} - m_RootOrder: 14 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000010874363134 MeshFilter: @@ -5485,9 +5685,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000014142736920} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1.0000001, y: 1.0000001, z: 0.025} m_Center: {x: 0, y: 0, z: 0} --- !u!114 &114000010401740614 @@ -5541,7 +5749,15 @@ MonoBehaviour: m_UnloadedTexture: {fileID: 2800000, guid: 92139e46e58d3924fb8e16ba42a0145f, type: 3} m_LoadedTexture: {fileID: 2800000, guid: e9a34c5f95833b248b106d4f7d83d9ad, type: 3} m_ErrorTexture: {fileID: 2800000, guid: 0c91e975bed1cd948a150b672f3fec48, type: 3} - m_LoadHelpText: Click to Load + m_LoadHelpText: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] m_LoadingOverlay: {fileID: 1000013864904278} references: version: 2 @@ -5571,13 +5787,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000014145540092} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: -0, z: -0.01} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000010489297534} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000013079542252 MeshFilter: @@ -5656,6 +5872,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000014265003938} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0.209, y: -0.406, z: -0.054000005} m_LocalScale: {x: 0.29999998, y: 0.29999998, z: 0.29999998} @@ -5664,7 +5881,6 @@ Transform: - {fileID: 332452329397556464} - {fileID: 4000011628422548} m_Father: {fileID: 4000010258256146} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000010574217940 MeshFilter: @@ -5724,9 +5940,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000014265003938} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 2, y: 1, z: 0.01} m_Center: {x: 0, y: 0, z: 0} --- !u!114 &114000012405969980 @@ -5831,6 +6055,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1021259386128138} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: -0.16, z: -0.05} m_LocalScale: {x: 1, y: 1, z: 1} @@ -5839,7 +6064,6 @@ Transform: - {fileID: 224789936601444018} - {fileID: 4882862779753528} m_Father: {fileID: 465812} - m_RootOrder: 21 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!23 &23005740735915826 MeshRenderer: @@ -5908,13 +6132,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1584545852907080} + serializedVersion: 2 m_LocalRotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071067} m_LocalPosition: {x: -0, y: 0, z: 0} m_LocalScale: {x: 100, y: 100, z: 100} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4882862779753528} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33710099620813864 MeshFilter: @@ -5998,7 +6222,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4932507317400606} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} @@ -6205,6 +6428,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1906655395918520} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0.209, y: 0.06400013, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} @@ -6213,7 +6437,6 @@ Transform: - {fileID: 4855091873576358} - {fileID: 4101333333006384} m_Father: {fileID: 4932507317400606} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &1950131066522348 GameObject: @@ -6240,13 +6463,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1950131066522348} + serializedVersion: 2 m_LocalRotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071067} m_LocalPosition: {x: -0, y: 0, z: 0} m_LocalScale: {x: 100, y: 100, z: 100} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4882862779753528} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33966215123458588 MeshFilter: @@ -6330,7 +6553,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000014190517824} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} @@ -6547,7 +6769,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000010713138772} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} @@ -6764,7 +6985,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000012135202400} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} @@ -6977,7 +7197,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000010287137376} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} @@ -7181,6 +7400,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1816486902914083968} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0.209, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} @@ -7189,7 +7409,6 @@ Transform: - {fileID: 1170610089143318067} - {fileID: 8020598781474349598} m_Father: {fileID: 1728879999287929109} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &2345216971250741339 GameObject: @@ -7216,13 +7435,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 2345216971250741339} + serializedVersion: 2 m_LocalRotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071067} m_LocalPosition: {x: -0, y: 0, z: 0} m_LocalScale: {x: 100, y: 100, z: 100} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 7047693795861342256} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &4058447100505187227 MeshFilter: @@ -7298,6 +7517,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 2503533423454172181} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: -0.1, z: -0.05} m_LocalScale: {x: 1, y: 1, z: 1} @@ -7306,7 +7526,6 @@ Transform: - {fileID: 5036818937176549477} - {fileID: 7047693795861342256} m_Father: {fileID: 465812} - m_RootOrder: 26 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!23 &6343569852496349475 MeshRenderer: @@ -7382,7 +7601,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 1728879999287929109} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} @@ -7596,7 +7814,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 465812} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} @@ -7769,7 +7986,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000013357198230} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} @@ -7990,7 +8206,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 465812} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} @@ -8203,7 +8418,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000010185127306} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} @@ -8413,13 +8627,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 8549073727040760058} + serializedVersion: 2 m_LocalRotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071067} m_LocalPosition: {x: -0, y: 0, z: 0} m_LocalScale: {x: 100, y: 100, z: 100} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 7047693795861342256} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &5826445933073688365 MeshFilter: @@ -8503,7 +8717,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 465812} - m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} @@ -8716,7 +8929,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000010258256146} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} @@ -8933,7 +9145,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000012309134638} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} @@ -9146,7 +9357,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000013940156938} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} diff --git a/Assets/Prefabs/Panels/PolyPanel.prefab.meta b/Assets/Prefabs/Panels/IcosaPanel.prefab.meta similarity index 100% rename from Assets/Prefabs/Panels/PolyPanel.prefab.meta rename to Assets/Prefabs/Panels/IcosaPanel.prefab.meta diff --git a/Assets/Prefabs/Panels/PolyPanel_Mobile.prefab b/Assets/Prefabs/Panels/IcosaPanel_Mobile.prefab similarity index 100% rename from Assets/Prefabs/Panels/PolyPanel_Mobile.prefab rename to Assets/Prefabs/Panels/IcosaPanel_Mobile.prefab diff --git a/Assets/Prefabs/Panels/PolyPanel_Mobile.prefab.meta b/Assets/Prefabs/Panels/IcosaPanel_Mobile.prefab.meta similarity index 100% rename from Assets/Prefabs/Panels/PolyPanel_Mobile.prefab.meta rename to Assets/Prefabs/Panels/IcosaPanel_Mobile.prefab.meta diff --git a/Assets/Prefabs/Panels/LabsPanel.prefab b/Assets/Prefabs/Panels/LabsPanel.prefab index 95ae0b3ae7..90f31902df 100644 --- a/Assets/Prefabs/Panels/LabsPanel.prefab +++ b/Assets/Prefabs/Panels/LabsPanel.prefab @@ -26,13 +26,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 111906} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: -0.1962, y: 0, z: 0} m_LocalScale: {x: 0.35, y: 0.35, z: 0.35} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 434412} - m_RootOrder: 5 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &3327986 MeshFilter: @@ -121,13 +121,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 132602} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 0.29, y: 0.1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 434412} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!65 &6572796 BoxCollider: @@ -137,9 +137,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 132602} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 0.65, y: 1, z: 0.1} m_Center: {x: 0, y: 0, z: 0} --- !u!1 &151652 @@ -167,13 +175,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 151652} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: -0.1083, y: 0, z: 0.0002105044} m_LocalScale: {x: 0.0375, y: 0.0375, z: 0.0375} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 434412} - m_RootOrder: 4 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &3363688 MeshFilter: @@ -249,13 +257,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 153348} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0.1} m_LocalScale: {x: 1, y: 1, z: 0.01} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 402684} - m_RootOrder: 16 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &3364774 MeshFilter: @@ -288,6 +296,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 160772} + serializedVersion: 2 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} @@ -311,7 +320,6 @@ Transform: - {fileID: 499404} - {fileID: 415298} m_Father: {fileID: 485948} - m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &162404 GameObject: @@ -337,6 +345,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 162404} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: -0.65, z: 0.05} m_LocalScale: {x: 2.5000002, y: 2.4999995, z: 2.5} @@ -350,7 +359,6 @@ Transform: - {fileID: 468986} - {fileID: 430698} m_Father: {fileID: 402684} - m_RootOrder: 13 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!114 &11452096 MonoBehaviour: @@ -417,13 +425,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 164352} + serializedVersion: 2 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_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 485948} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!65 &6531256 BoxCollider: @@ -433,9 +441,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 164352} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1.9, y: 2.4, z: 0.5} m_Center: {x: 0, y: 0, z: 0} --- !u!1 &168032 @@ -462,13 +478,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 168032} + serializedVersion: 2 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_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 402684} - m_RootOrder: 15 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!65 &6547610 BoxCollider: @@ -478,9 +494,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 168032} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1.4, y: 1.9, z: 0.02} m_Center: {x: 0, y: 0, z: 0} --- !u!1 &190538 @@ -508,13 +532,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 190538} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 0.181, y: 0.0375, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 434412} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!23 &2394778 MeshRenderer: @@ -592,13 +616,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 193010} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: -0.08, y: 0, z: 0} m_LocalScale: {x: 0.01, y: 0.03, z: 0.01} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 434412} - m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &3387922 MeshFilter: @@ -689,13 +713,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 197878} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0.1965, y: 0, z: 0} m_LocalScale: {x: 0.35, y: 0.35, z: 0.35} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 434412} - m_RootOrder: 6 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &3300622 MeshFilter: @@ -785,13 +809,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 199026} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 1, w: 0} m_LocalPosition: {x: 0.1088, y: 0, z: 0.00021062419} m_LocalScale: {x: 0.0375, y: 0.0375, z: 0.0375} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 434412} - m_RootOrder: 3 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &3316150 MeshFilter: @@ -869,6 +893,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 199434} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 10, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} @@ -878,7 +903,6 @@ Transform: - {fileID: 442914} - {fileID: 402684} m_Father: {fileID: 0} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!114 &114019824221785570 MonoBehaviour: @@ -1028,13 +1052,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000010690061500} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: -0.207, y: -0.3, z: 0.05} + m_LocalPosition: {x: 0, y: -0.3, z: 0.05} m_LocalScale: {x: 0.35, y: 0.35, z: 0.35} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 402684} - m_RootOrder: 11 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000013755556650 MeshFilter: @@ -1094,9 +1118,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000010690061500} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1, y: 1, z: 0.1} m_Center: {x: -0.000000074505806, y: 0.000000022351742, z: 0} --- !u!114 &114000011226708614 @@ -1204,13 +1236,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000010708462674} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0.6000004, z: 0.05} m_LocalScale: {x: 0.35, y: 0.35, z: 0.35} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 402684} - m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000010418119032 MeshFilter: @@ -1270,9 +1302,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000010708462674} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1, y: 1, z: 0.1} m_Center: {x: -0.000000074505806, y: 0.000000022351742, z: 0} --- !u!114 &114000012887931942 @@ -1380,13 +1420,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000011220362354} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: -0.415, y: 0.6, z: 0.05} m_LocalScale: {x: 0.35, y: 0.35, z: 0.35} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 402684} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000010384743742 MeshFilter: @@ -1446,9 +1486,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000011220362354} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1, y: 1, z: 0.1} m_Center: {x: -0.000000074505806, y: 0.000000022351742, z: 0} --- !u!114 &114000013288942322 @@ -1556,13 +1604,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000012054711126} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0.415, y: 0.15, z: 0.05} m_LocalScale: {x: 0.35, y: 0.35, z: 0.35} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 402684} - m_RootOrder: 6 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000013414599442 MeshFilter: @@ -1622,9 +1670,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000012054711126} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1, y: 1, z: 0.1} m_Center: {x: -0.000000074505806, y: 0.000000022351742, z: 0} --- !u!114 &114000011947978538 @@ -1731,13 +1787,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000012292180826} + serializedVersion: 2 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_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 402684} - m_RootOrder: 14 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000013181835044 MeshFilter: @@ -1829,13 +1885,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000013682514104} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: -0.415, y: 0.15, z: 0.05} m_LocalScale: {x: 0.35, y: 0.35, z: 0.35} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 402684} - m_RootOrder: 7 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000012285989520 MeshFilter: @@ -1946,9 +2002,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000013682514104} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1, y: 1, z: 0.1} m_Center: {x: 0, y: 0, z: 0} --- !u!1 &1000013998383226 @@ -1976,13 +2040,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000013998383226} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1.5, y: 1.9, z: 2.4} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 485948} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000011026480406 MeshFilter: @@ -2061,13 +2125,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000014165885050} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0.6, z: 0.05} m_LocalScale: {x: 0.35, y: 0.35, z: 0.35} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 402684} - m_RootOrder: 4 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000012292458500 MeshFilter: @@ -2127,9 +2191,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000014165885050} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1, y: 1, z: 0.1} m_Center: {x: -0.000000074505806, y: 0.000000022351742, z: 0} --- !u!114 &114000012043531378 @@ -2237,13 +2309,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1634642417305556} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0.15, z: 0.05} m_LocalScale: {x: 0.35, y: 0.35, z: 0.35} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 402684} - m_RootOrder: 10 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33062622632853984 MeshFilter: @@ -2303,9 +2375,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1634642417305556} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1, y: 1, z: 0.01} m_Center: {x: 0, y: 0, z: -0.05} --- !u!114 &114328378359043972 @@ -2386,13 +2466,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1016131236980122382} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0.20799999, y: -0.3, z: 0.05} + m_LocalPosition: {x: 0.415, y: -0.3, z: 0.05} m_LocalScale: {x: 0.35, y: 0.35, z: 0.35} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 402684} - m_RootOrder: 12 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &7459773723550717888 MeshFilter: @@ -2503,9 +2583,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1016131236980122382} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1, y: 1, z: 0.1} m_Center: {x: 0, y: 0, z: 0} --- !u!1 &2720949118896594763 @@ -2522,12 +2610,12 @@ GameObject: - component: {fileID: 4847028611873093419} - component: {fileID: 8302968001735879957} m_Layer: 16 - m_Name: PolyLibrary + m_Name: IcosaLibrary m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 - m_IsActive: 0 + m_IsActive: 1 --- !u!4 &1643836230823162033 Transform: m_ObjectHideFlags: 0 @@ -2535,13 +2623,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 2720949118896594763} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: -0.415, y: 0.15, z: 0.05} + m_LocalPosition: {x: -0.415, y: -0.3, z: 0.05} m_LocalScale: {x: 0.35, y: 0.35, z: 0.35} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 402684} - m_RootOrder: 9 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &2078078264413487613 MeshFilter: @@ -2652,9 +2740,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 2720949118896594763} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1, y: 1, z: 0.01} m_Center: {x: 0, y: 0, z: -0.05} --- !u!1 &4011871447704911063 @@ -2684,13 +2780,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 4011871447704911063} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0.415, y: 0.15, z: 0.049999237} m_LocalScale: {x: 0.35, y: 0.35, z: 0.35} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 402684} - m_RootOrder: 5 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &4510907067803236372 MeshFilter: @@ -2801,9 +2897,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 4011871447704911063} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1, y: 1, z: 0.01} m_Center: {x: 0, y: 0, z: -0.05} --- !u!1 &6294566030148222674 @@ -2833,13 +2937,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 6294566030148222674} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0.415, y: 0.6000004, z: 0.05} m_LocalScale: {x: 0.35, y: 0.35, z: 0.35} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 402684} - m_RootOrder: 3 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &6280797664358514420 MeshFilter: @@ -2899,9 +3003,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 6294566030148222674} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1, y: 1, z: 0.1} m_Center: {x: -0.000000074505806, y: 0.000000022351742, z: 0} --- !u!114 &6254052937444237984 @@ -3009,13 +3121,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 6295169059849678530} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: -0.415, y: 0.14999962, z: 0.05} m_LocalScale: {x: 0.35, y: 0.35, z: 0.35} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 402684} - m_RootOrder: 8 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &6280936243828533384 MeshFilter: @@ -3075,9 +3187,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 6295169059849678530} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1, y: 1, z: 0.1} m_Center: {x: -0.000000074505806, y: 0.000000022351742, z: 0} --- !u!114 &6253917691903006574 @@ -3168,13 +3288,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 6464453085985281487} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: -0.415, y: 0.6000004, z: 0.05} m_LocalScale: {x: 0.35, y: 0.35, z: 0.35} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 402684} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &6468953577034300013 MeshFilter: @@ -3234,9 +3354,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 6464453085985281487} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1, y: 1, z: 0.01} m_Center: {x: 0, y: 0, z: 0} --- !u!114 &6351870043360636743 diff --git a/Assets/Prefabs/Panels/LabsPanel_Mobile.prefab b/Assets/Prefabs/Panels/LabsPanel_Mobile.prefab index ea2fc049ca..32ce3de82f 100644 --- a/Assets/Prefabs/Panels/LabsPanel_Mobile.prefab +++ b/Assets/Prefabs/Panels/LabsPanel_Mobile.prefab @@ -24,13 +24,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 153348} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0.1} m_LocalScale: {x: 0.68, y: 0.48000002, z: 0.01} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 402684} - m_RootOrder: 10 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &3364774 MeshFilter: @@ -63,6 +63,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 160772} + serializedVersion: 2 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} @@ -70,9 +71,9 @@ Transform: m_Children: - {fileID: 4000012490214276} - {fileID: 3219221680988349883} - - {fileID: 1139538046860859100} - {fileID: 4626429713668410} - {fileID: 4000011596321798} + - {fileID: 1139538046860859100} - {fileID: 2468152952838901612} - {fileID: 8809421544085413876} - {fileID: 2468055462235645184} @@ -80,7 +81,6 @@ Transform: - {fileID: 4000011486688576} - {fileID: 415298} m_Father: {fileID: 485948} - m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &164352 GameObject: @@ -106,13 +106,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 164352} + serializedVersion: 2 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_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 485948} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!65 &6531256 BoxCollider: @@ -122,9 +122,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 164352} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1.9, y: 1.6, z: 0.5} m_Center: {x: 0, y: 0, z: 0} --- !u!1 &168032 @@ -151,13 +159,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 168032} + serializedVersion: 2 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_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 402684} - m_RootOrder: 8 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!65 &6547610 BoxCollider: @@ -167,9 +175,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 168032} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1.4, y: 1.1, z: 0.02} m_Center: {x: 0, y: 0, z: 0} --- !u!1 &199434 @@ -198,6 +214,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 199434} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 1.788, y: 10, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} @@ -207,7 +224,6 @@ Transform: - {fileID: 442914} - {fileID: 402684} m_Father: {fileID: 0} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!114 &114019824221785570 MonoBehaviour: @@ -357,13 +373,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000010708462674} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0.415, y: 0.212, z: 0.05} m_LocalScale: {x: 0.35, y: 0.35, z: 0.35} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 402684} - m_RootOrder: 4 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000010418119032 MeshFilter: @@ -423,9 +439,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000010708462674} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1, y: 1, z: 0.1} m_Center: {x: -0.000000074505806, y: 0.000000022351742, z: 0} --- !u!114 &114000012887931942 @@ -532,13 +556,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000012292180826} + serializedVersion: 2 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_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 402684} - m_RootOrder: 9 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000013181835044 MeshFilter: @@ -630,13 +654,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000013682514104} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: -0.415, y: 0.212, z: 0.05} m_LocalScale: {x: 0.35, y: 0.35, z: 0.35} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 402684} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000012285989520 MeshFilter: @@ -747,9 +771,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000013682514104} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1, y: 1, z: 0.1} m_Center: {x: 0, y: 0, z: 0} --- !u!1 &1000013998383226 @@ -777,13 +809,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000013998383226} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1.5, y: 1.1, z: 2.4} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 485948} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000011026480406 MeshFilter: @@ -862,13 +894,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1634642417305556} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0.212, z: 0.05} m_LocalScale: {x: 0.35, y: 0.35, z: 0.35} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 402684} - m_RootOrder: 3 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33062622632853984 MeshFilter: @@ -928,9 +960,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1634642417305556} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1, y: 1, z: 0.01} m_Center: {x: 0, y: 0, z: -0.05} --- !u!114 &114328378359043972 @@ -1011,13 +1051,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 2471131391549106940} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0.6149999, y: -0.2119999, z: 0.05} m_LocalScale: {x: 0.35, y: 0.35, z: 0.35} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 402684} - m_RootOrder: 7 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &2465741338722790106 MeshFilter: @@ -1077,9 +1117,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 2471131391549106940} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1, y: 1, z: 0.1} m_Center: {x: -0.000000074505806, y: 0.000000022351742, z: 0} --- !u!114 &2583710071636260494 @@ -1187,13 +1235,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 2471663056078174956} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: -0.215, y: -0.2119999, z: 0.05} + m_LocalPosition: {x: 0, y: -0.212, z: 0.05} m_LocalScale: {x: 0.35, y: 0.35, z: 0.35} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 402684} - m_RootOrder: 5 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &2466755025299766438 MeshFilter: @@ -1253,9 +1301,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 2471663056078174956} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1, y: 1, z: 0.1} m_Center: {x: -0.000000074505806, y: 0.000000022351742, z: 0} --- !u!114 &2583821116712190784 @@ -1346,13 +1402,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 3217728787759546849} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: -0.41499996, y: 0.2119999, z: 0.05} m_LocalScale: {x: 0.35, y: 0.35, z: 0.35} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 402684} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &3231233352384081475 MeshFilter: @@ -1412,9 +1468,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 3217728787759546849} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1, y: 1, z: 0.01} m_Center: {x: 0, y: 0, z: 0} --- !u!114 &3258234186096769897 @@ -1510,12 +1574,12 @@ GameObject: - component: {fileID: 1408412152701508224} - component: {fileID: 769398838496988592} m_Layer: 16 - m_Name: PolyLibrary + m_Name: IcosaLibrary m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 - m_IsActive: 0 + m_IsActive: 1 --- !u!4 &1139538046860859100 Transform: m_ObjectHideFlags: 0 @@ -1523,13 +1587,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 7776948797728914220} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: -0.415, y: 0.212, z: 0.05} + m_LocalPosition: {x: -0.415, y: -0.212, z: 0.05} m_LocalScale: {x: 0.35, y: 0.35, z: 0.35} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 402684} - m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &7705200013302925820 MeshFilter: @@ -1627,7 +1691,7 @@ MonoBehaviour: m_HoverScale: 1.1 m_HoverBoxColliderGrow: 0.2 m_AddOverlay: 0 - m_Type: 29 + m_Type: 22 m_AlwaysSpawn: 0 references: version: 2 @@ -1640,9 +1704,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 7776948797728914220} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1, y: 1, z: 0.01} m_Center: {x: 0, y: 0, z: -0.05} --- !u!1001 &1958996772086488720 @@ -1650,6 +1722,7 @@ PrefabInstance: m_ObjectHideFlags: 0 serializedVersion: 2 m_Modification: + serializedVersion: 3 m_TransformParent: {fileID: 402684} m_Modifications: - target: {fileID: 3143605885771001294, guid: 6e69b3bc22681fb44ac931399886cd69, @@ -1665,7 +1738,7 @@ PrefabInstance: - target: {fileID: 7020719392467468644, guid: 6e69b3bc22681fb44ac931399886cd69, type: 3} propertyPath: m_LocalPosition.x - value: 0.19999993 + value: 0.415 objectReference: {fileID: 0} - target: {fileID: 7020719392467468644, guid: 6e69b3bc22681fb44ac931399886cd69, type: 3} @@ -1713,6 +1786,9 @@ PrefabInstance: value: 0 objectReference: {fileID: 0} m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: 6e69b3bc22681fb44ac931399886cd69, type: 3} --- !u!4 &8809421544085413876 stripped Transform: diff --git a/Assets/Prefabs/Panels/SketchbookPanel.prefab b/Assets/Prefabs/Panels/SketchbookPanel.prefab index 5a8693b797..9c4dfab59b 100644 --- a/Assets/Prefabs/Panels/SketchbookPanel.prefab +++ b/Assets/Prefabs/Panels/SketchbookPanel.prefab @@ -28,6 +28,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 101820} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0.7678, y: -0.5287, z: -0.03} m_LocalScale: {x: 0.45, y: 0.45, z: 0.45} @@ -36,7 +37,6 @@ Transform: - {fileID: 4000012287575696} - {fileID: 4044106463973608} m_Father: {fileID: 473678} - m_RootOrder: 12 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &3348596 MeshFilter: @@ -96,9 +96,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 101820} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1.0000001, y: 1.0000001, z: 0.025} m_Center: {x: 0, y: 0, z: 0} --- !u!114 &11403980 @@ -193,13 +201,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 102468} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: -0.42, y: -0.991, z: -0.04} m_LocalScale: {x: 0.25, y: 0.25, z: 0.25} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 473678} - m_RootOrder: 17 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &3392684 MeshFilter: @@ -259,9 +267,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 102468} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1, y: 1, z: 0.01} m_Center: {x: 0, y: 0, z: 0} --- !u!114 &11400036 @@ -342,13 +358,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 109144} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0.5, z: -0.0025} m_LocalScale: {x: 1, y: 0.02857143, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 447228} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &3375698 MeshFilter: @@ -425,6 +441,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 109932} + serializedVersion: 2 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} @@ -433,7 +450,6 @@ Transform: - {fileID: 400638} - {fileID: 473678} m_Father: {fileID: 0} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!114 &2478559423573741591 MonoBehaviour: @@ -611,7 +627,7 @@ MonoBehaviour: m_NoShowcaseMessage: {fileID: 1147890328312932} m_ContactingServerMessage: {fileID: 1000011835935838} m_OutOfDateMessage: {fileID: 1000012586849750} - m_NoPolyConnectionMessage: {fileID: 4374687820491222719} + m_NoIcosaConnectionMessage: {fileID: 4374687820491222719} m_OnlineGalleryButtonRenderer: {fileID: 23175542353181748} m_IconsOnFirstPage: - {fileID: 142432} @@ -688,13 +704,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 116946} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: -0, z: -0.1} m_LocalScale: {x: 2, y: 2, z: 2} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 475426} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!23 &2321406 MeshRenderer: @@ -785,13 +801,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 125268} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: -0.49999997, z: -0.002} m_LocalScale: {x: 1, y: 0.028571434, z: 2} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 458322} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &3362976 MeshFilter: @@ -867,13 +883,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 126012} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0.1, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 405018} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!65 &6504288 BoxCollider: @@ -883,9 +899,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 126012} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 2.44, y: 2.7, z: 0.5} m_Center: {x: 0, y: -0.06, z: 0} --- !u!1 &127584 @@ -915,6 +939,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 127584} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: -0.84, y: 0.4779, z: -0.0301} m_LocalScale: {x: 0.436, y: 0.436, z: 0.436} @@ -924,7 +949,6 @@ Transform: - {fileID: 458322} - {fileID: 431352} m_Father: {fileID: 473678} - m_RootOrder: 13 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &3366994 MeshFilter: @@ -984,9 +1008,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 127584} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1.12, y: 0.73, z: 0.1} m_Center: {x: 0, y: 0, z: 0} --- !u!114 &11443276 @@ -1066,6 +1098,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 129824} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: -0.132, y: -0.991, z: -0.04} m_LocalScale: {x: 0.15, y: 0.15, z: 0.15} @@ -1073,7 +1106,6 @@ Transform: m_Children: - {fileID: 440846} m_Father: {fileID: 473678} - m_RootOrder: 18 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &3302166 MeshFilter: @@ -1133,9 +1165,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 129824} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1, y: 1, z: 0.1} m_Center: {x: 0, y: 0, z: -0.1} --- !u!114 &11474338 @@ -1216,13 +1256,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 130496} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: -0.49999997, z: -0.002} m_LocalScale: {x: 1, y: 0.028571434, z: 2} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 479382} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &3319264 MeshFilter: @@ -1299,13 +1339,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 131562} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: -0, z: -0.1} m_LocalScale: {x: 2, y: 2, z: 2} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 423072} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!23 &2305932 MeshRenderer: @@ -1396,6 +1436,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 135162} + serializedVersion: 2 m_LocalRotation: {x: 0.5000001, y: 0.5, z: -0.5, w: 0.49999994} m_LocalPosition: {x: 0, y: 1.2142847, z: 0.4594286} m_LocalScale: {x: 0.9142857, y: 1, z: 1} @@ -1404,7 +1445,6 @@ Transform: - {fileID: 432950} - {fileID: 471736} m_Father: {fileID: 490548} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &3351754 MeshFilter: @@ -1481,13 +1521,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 136488} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0.49999997, z: -0.002} m_LocalScale: {x: 1, y: 0.028571434, z: 2} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 458322} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &3389112 MeshFilter: @@ -1566,6 +1606,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 136962} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0.63, y: -0.991, z: -0.04} m_LocalScale: {x: 0.15, y: 0.15, z: 0.15} @@ -1573,7 +1614,6 @@ Transform: m_Children: - {fileID: 440778} m_Father: {fileID: 473678} - m_RootOrder: 22 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &3357382 MeshFilter: @@ -1633,9 +1673,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 136962} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1, y: 1, z: 0.1} m_Center: {x: 0, y: 0, z: -0.1} --- !u!114 &11499286 @@ -1714,6 +1762,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 138864} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0.1, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} @@ -1763,7 +1812,6 @@ Transform: - {fileID: 4604395735417884} - {fileID: 4000012925136122} m_Father: {fileID: 405018} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &142258 GameObject: @@ -1792,6 +1840,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 142258} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0.436, y: -0.991, z: -0.04} m_LocalScale: {x: 0.15, y: 0.15, z: 0.15} @@ -1799,7 +1848,6 @@ Transform: m_Children: - {fileID: 408284} m_Father: {fileID: 473678} - m_RootOrder: 21 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &3356862 MeshFilter: @@ -1859,9 +1907,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 142258} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1, y: 1, z: 0.1} m_Center: {x: 0, y: 0, z: -0.1} --- !u!114 &11408728 @@ -1945,6 +2001,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 142432} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: -0.012, y: 0.249, z: -0.03} m_LocalScale: {x: 0.935, y: 0.935, z: 0.45} @@ -1953,7 +2010,6 @@ Transform: - {fileID: 4000012999570806} - {fileID: 4819910167133682} m_Father: {fileID: 473678} - m_RootOrder: 3 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &3345518 MeshFilter: @@ -2013,9 +2069,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 142432} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1.0000001, y: 1.0000001, z: 0.025} m_Center: {x: 0, y: 0, z: 0} --- !u!114 &11452860 @@ -2108,6 +2172,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 148956} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: -0.7071068, w: 0.7071067} m_LocalPosition: {x: 0, y: 0.35714287, z: 0.002285719} m_LocalScale: {x: 1.7142856, y: 1, z: 1} @@ -2116,7 +2181,6 @@ Transform: - {fileID: 434670} - {fileID: 454538} m_Father: {fileID: 490548} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &3365804 MeshFilter: @@ -2196,6 +2260,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 153576} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0.247, y: -0.008, z: -0.03} m_LocalScale: {x: 0.45, y: 0.45, z: 0.45} @@ -2204,7 +2269,6 @@ Transform: - {fileID: 4000013461333742} - {fileID: 4192096235684524} m_Father: {fileID: 473678} - m_RootOrder: 8 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &3354416 MeshFilter: @@ -2264,9 +2328,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 153576} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1.0000001, y: 1.0000001, z: 0.025} m_Center: {x: 0, y: 0, z: 0} --- !u!114 &11475750 @@ -2362,6 +2434,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 155428} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0.7698, y: -0.012, z: -0.03} m_LocalScale: {x: 0.45, y: 0.45, z: 0.45} @@ -2370,7 +2443,6 @@ Transform: - {fileID: 4000011053558040} - {fileID: 4969141364180978} m_Father: {fileID: 473678} - m_RootOrder: 9 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &3388248 MeshFilter: @@ -2430,9 +2502,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 155428} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1.0000001, y: 1.0000001, z: 0.025} m_Center: {x: 0, y: 0, z: 0} --- !u!114 &11413066 @@ -2527,6 +2607,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 155754} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: -0.84, y: -0.1593, z: -0.0301} m_LocalScale: {x: 0.43600002, y: 0.43600002, z: 0.43600002} @@ -2536,7 +2617,6 @@ Transform: - {fileID: 479382} - {fileID: 499714} m_Father: {fileID: 473678} - m_RootOrder: 15 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &3306764 MeshFilter: @@ -2596,9 +2676,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 155754} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1.12, y: 0.73, z: 0.1} m_Center: {x: 0, y: 0, z: 0} --- !u!114 &11456692 @@ -2676,13 +2764,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 162048} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: -0.49999997, z: 0.00228548} m_LocalScale: {x: 1, y: 0.028571434, z: 0.9142854} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 431352} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &3335230 MeshFilter: @@ -2762,6 +2850,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 166396} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0.247, y: -0.5287, z: -0.03} m_LocalScale: {x: 0.45, y: 0.45, z: 0.45} @@ -2770,7 +2859,6 @@ Transform: - {fileID: 4000013138638754} - {fileID: 4916153691783676} m_Father: {fileID: 473678} - m_RootOrder: 11 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &3390222 MeshFilter: @@ -2830,9 +2918,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 166396} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1.0000001, y: 1.0000001, z: 0.025} m_Center: {x: 0, y: 0, z: 0} --- !u!114 &11452280 @@ -2928,6 +3024,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 167238} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0.7698, y: 0.5129, z: -0.03} m_LocalScale: {x: 0.45, y: 0.45, z: 0.45} @@ -2936,7 +3033,6 @@ Transform: - {fileID: 4000013478852842} - {fileID: 4648845093172990} m_Father: {fileID: 473678} - m_RootOrder: 6 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &3309702 MeshFilter: @@ -2996,9 +3092,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 167238} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1.0000001, y: 1.0000001, z: 0.025} m_Center: {x: 0, y: 0, z: 0} --- !u!114 &11486740 @@ -3091,13 +3195,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 167948} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: -0, z: -0.1} m_LocalScale: {x: 2, y: 2, z: 2} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 416688} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!23 &2384872 MeshRenderer: @@ -3188,13 +3292,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 168646} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: -0.1} m_LocalScale: {x: 2, y: 2, z: 2} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 499328} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!23 &2380942 MeshRenderer: @@ -3288,6 +3392,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 169670} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: -0.2737, y: -0.5287, z: -0.03} m_LocalScale: {x: 0.45, y: 0.45, z: 0.45} @@ -3296,7 +3401,6 @@ Transform: - {fileID: 4000011500092316} - {fileID: 4069340866196592} m_Father: {fileID: 473678} - m_RootOrder: 10 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &3348150 MeshFilter: @@ -3356,9 +3460,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 169670} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1.0000001, y: 1.0000001, z: 0.025} m_Center: {x: 0, y: 0, z: 0} --- !u!114 &11490938 @@ -3453,6 +3565,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 171976} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0.245, y: -0.991, z: -0.04} m_LocalScale: {x: 0.15, y: 0.15, z: 0.15} @@ -3460,7 +3573,6 @@ Transform: m_Children: - {fileID: 420674} m_Father: {fileID: 473678} - m_RootOrder: 20 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &3376740 MeshFilter: @@ -3520,9 +3632,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 171976} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1, y: 1, z: 0.1} m_Center: {x: 0, y: 0, z: -0.1} --- !u!114 &11406912 @@ -3603,13 +3723,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 172220} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: -0.49999997, z: 0.00228548} m_LocalScale: {x: 1, y: 0.028571434, z: 0.9142854} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 499714} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &3364482 MeshFilter: @@ -3686,13 +3806,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 173116} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: -0.5, z: -0.0024999883} m_LocalScale: {x: 1, y: 0.028571432, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 447228} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &3359794 MeshFilter: @@ -3771,6 +3891,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 174376} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0.058, y: -0.991, z: -0.04} m_LocalScale: {x: 0.15, y: 0.15, z: 0.15} @@ -3778,7 +3899,6 @@ Transform: m_Children: - {fileID: 494418} m_Father: {fileID: 473678} - m_RootOrder: 19 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &3373530 MeshFilter: @@ -3838,9 +3958,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 174376} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1, y: 1, z: 0.1} m_Center: {x: 0, y: 0, z: -0.1} --- !u!114 &11468240 @@ -3921,6 +4049,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 175552} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: -0.7071068, w: 0.7071067} m_LocalPosition: {x: 0, y: -1.0697142, z: 0.9165714} m_LocalScale: {x: 4.5714283, y: 1, z: 1} @@ -3929,7 +4058,6 @@ Transform: - {fileID: 441124} - {fileID: 427536} m_Father: {fileID: 490548} - m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &3319242 MeshFilter: @@ -4006,13 +4134,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 176914} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: -0.5, z: -0.0024999883} m_LocalScale: {x: 1, y: 0.028571432, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 412038} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &3313266 MeshFilter: @@ -4092,6 +4220,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 177278} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0.249, y: 0.5129, z: -0.03} m_LocalScale: {x: 0.45, y: 0.45, z: 0.45} @@ -4100,7 +4229,6 @@ Transform: - {fileID: 4000012910955364} - {fileID: 4840805683560546} m_Father: {fileID: 473678} - m_RootOrder: 5 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &3327974 MeshFilter: @@ -4160,9 +4288,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 177278} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1.0000001, y: 1.0000001, z: 0.025} m_Center: {x: 0, y: 0, z: 0} --- !u!114 &11431774 @@ -4258,6 +4394,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 178250} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: -0.2737, y: -0.008, z: -0.03} m_LocalScale: {x: 0.45, y: 0.45, z: 0.45} @@ -4266,7 +4403,6 @@ Transform: - {fileID: 4000012616996494} - {fileID: 4284873399471688} m_Father: {fileID: 473678} - m_RootOrder: 7 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &3363168 MeshFilter: @@ -4326,9 +4462,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 178250} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1.0000001, y: 1.0000001, z: 0.025} m_Center: {x: 0, y: 0, z: 0} --- !u!114 &11477404 @@ -4421,6 +4565,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 178916} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: -0.7071068, w: 0.7071067} m_LocalPosition: {x: 0, y: 0.35714287, z: 0.002285719} m_LocalScale: {x: 1.7142856, y: 1, z: 1} @@ -4429,7 +4574,6 @@ Transform: - {fileID: 465110} - {fileID: 484996} m_Father: {fileID: 468632} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &3314012 MeshFilter: @@ -4506,13 +4650,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 183508} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0.49999997, z: -0.002} m_LocalScale: {x: 1, y: 0.028571434, z: 2} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 479382} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &3395878 MeshFilter: @@ -4589,13 +4733,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 183652} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: -0, z: -0.1} m_LocalScale: {x: 2, y: 2, z: 2} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 494534} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!23 &2397020 MeshRenderer: @@ -4686,13 +4830,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 188732} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0.5, z: -0.0025} m_LocalScale: {x: 1, y: 0.02857143, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 412038} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &3342042 MeshFilter: @@ -4769,6 +4913,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 192230} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: -0.7071068, w: 0.7071067} m_LocalPosition: {x: 0, y: -1.0697142, z: 0.9165714} m_LocalScale: {x: 4.5714283, y: 1, z: 1} @@ -4777,7 +4922,6 @@ Transform: - {fileID: 441958} - {fileID: 498352} m_Father: {fileID: 468632} - m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &3374636 MeshFilter: @@ -4854,13 +4998,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 194474} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0.49999997, z: 0.0022855483} m_LocalScale: {x: 1, y: 0.028571434, z: 0.9142854} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 431352} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &3334046 MeshFilter: @@ -4937,6 +5081,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 195798} + serializedVersion: 2 m_LocalRotation: {x: 0.5000001, y: 0.5, z: -0.5, w: 0.49999994} m_LocalPosition: {x: 0, y: 1.2142847, z: 0.4594286} m_LocalScale: {x: 0.9142857, y: 1, z: 1} @@ -4945,7 +5090,6 @@ Transform: - {fileID: 453004} - {fileID: 467276} m_Father: {fileID: 468632} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &3326064 MeshFilter: @@ -5021,13 +5165,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 196078} + serializedVersion: 2 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_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 473678} - m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!65 &6509770 BoxCollider: @@ -5037,9 +5181,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 196078} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 2.44, y: 2.7, z: 0.042} m_Center: {x: 0, y: -0.06, z: -0.01} --- !u!1 &196312 @@ -5069,13 +5221,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 196312} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0.912, y: -0.991, z: -0.04} m_LocalScale: {x: 0.25, y: 0.25, z: 0.25} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 473678} - m_RootOrder: 23 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &3342126 MeshFilter: @@ -5135,9 +5287,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 196312} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1, y: 1, z: 0.01} m_Center: {x: 0, y: 0, z: 0} --- !u!114 &11459642 @@ -5218,13 +5378,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 197350} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0.49999997, z: 0.0022855483} m_LocalScale: {x: 1, y: 0.028571434, z: 0.9142854} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 499714} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &3369242 MeshFilter: @@ -5301,13 +5461,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000010118716738} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: -0.49999997, z: -0.002} m_LocalScale: {x: 1, y: 0.028571434, z: 2} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000011206878738} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000011125244486 MeshFilter: @@ -5384,6 +5544,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000010134702830} + serializedVersion: 2 m_LocalRotation: {x: 0.5000001, y: 0.5, z: -0.5, w: 0.49999994} m_LocalPosition: {x: 0, y: 1.2142847, z: 0.4594286} m_LocalScale: {x: 0.9142857, y: 1, z: 1} @@ -5392,7 +5553,6 @@ Transform: - {fileID: 4000010892569700} - {fileID: 4000013078219060} m_Father: {fileID: 4000010470004098} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000011206434982 MeshFilter: @@ -5472,6 +5632,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000010241860486} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: -0.2717, y: 0.5129, z: -0.03} m_LocalScale: {x: 0.45, y: 0.45, z: 0.45} @@ -5480,7 +5641,6 @@ Transform: - {fileID: 4000011338142394} - {fileID: 4758236918301830} m_Father: {fileID: 473678} - m_RootOrder: 4 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000012812584494 MeshFilter: @@ -5540,9 +5700,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000010241860486} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1.0000001, y: 1.0000001, z: 0.025} m_Center: {x: 0, y: 0, z: 0} --- !u!114 &114000013156271550 @@ -5642,7 +5810,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000013760615668} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} @@ -5852,13 +6019,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000010365406468} + serializedVersion: 2 m_LocalRotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071067} m_LocalPosition: {x: -0, y: 0, z: 0} m_LocalScale: {x: 100, y: 100, z: 100} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000013868811186} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000011204178654 MeshFilter: @@ -5933,6 +6100,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000010401472448} + serializedVersion: 2 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} @@ -5942,7 +6110,6 @@ Transform: - {fileID: 4000014046535472} - {fileID: 4000013013276346} m_Father: {fileID: 473678} - m_RootOrder: 42 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &1000010567837980 GameObject: @@ -5970,13 +6137,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000010567837980} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: -0.1212, y: 0.383, z: -0.041999996} m_LocalScale: {x: 0.17, y: 0.17, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000013760615668} - m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000011881333540 MeshFilter: @@ -5994,9 +6161,17 @@ MeshCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000010567837980} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 4 + serializedVersion: 5 m_Convex: 0 m_CookingOptions: 30 m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} @@ -6065,6 +6240,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000010667475366} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0.000000014901161, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} @@ -6073,7 +6249,6 @@ Transform: - {fileID: 4000011744107576} - {fileID: 4000011886445864} m_Father: {fileID: 4000011114460008} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &1000010683355590 GameObject: @@ -6102,13 +6277,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000010683355590} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: -0.839, y: -0.991, z: -0.0311} m_LocalScale: {x: 0.25, y: 0.25, z: 0.25} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 473678} - m_RootOrder: 25 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000012255737950 MeshFilter: @@ -6168,9 +6343,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000010683355590} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1.0000001, y: 1.0000001, z: 0.1} m_Center: {x: 0, y: 0, z: 0} --- !u!114 &114911010639464544 @@ -6297,13 +6480,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000010744527238} + serializedVersion: 2 m_LocalRotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071067} m_LocalPosition: {x: -0, y: 0, z: 0} m_LocalScale: {x: 100, y: 100, z: 100} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000013175241986} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000012057045804 MeshFilter: @@ -6379,6 +6562,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000010821915206} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0.24, y: 0, z: -0.1} m_LocalScale: {x: 1, y: 1, z: 1} @@ -6389,7 +6573,6 @@ Transform: - {fileID: 4000012999227018} - {fileID: 4000013454894384} m_Father: {fileID: 473678} - m_RootOrder: 34 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!23 &23000010582741524 MeshRenderer: @@ -6460,13 +6643,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000010881089914} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0.3, y: -0.25, z: -0.05} m_LocalScale: {x: 0.55, y: 0.55, z: 0.35} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 476782} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000011808528658 MeshFilter: @@ -6526,9 +6709,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000010881089914} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 0.7, y: 1, z: 0.025} m_Center: {x: 0, y: 0, z: 0} --- !u!114 &114095498643358690 @@ -6605,13 +6796,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000011094475738} + serializedVersion: 2 m_LocalRotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071067} m_LocalPosition: {x: -0, y: 0, z: 0} m_LocalScale: {x: 100, y: 100, z: 100} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000012925136122} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000011121147842 MeshFilter: @@ -6688,13 +6879,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000011216287484} + serializedVersion: 2 m_LocalRotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071067} m_LocalPosition: {x: -0, y: 0, z: 0} m_LocalScale: {x: 100, y: 100, z: 100} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000013454894384} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000012369206972 MeshFilter: @@ -6771,13 +6962,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000011517226962} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0.49999997, z: -0.002} m_LocalScale: {x: 1, y: 0.028571434, z: 2} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000011206878738} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000011120581400 MeshFilter: @@ -6856,13 +7047,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000011551410764} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0.3, y: -0.25, z: -0.05} m_LocalScale: {x: 0.55, y: 0.55, z: 0.35} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000010333377928} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000011412534472 MeshFilter: @@ -6922,9 +7113,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000011551410764} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 0.7, y: 1, z: 0.025} m_Center: {x: 0, y: 0, z: 0} --- !u!114 &114335706120377868 @@ -7003,6 +7202,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000011622452938} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: -0.84, y: 0.1593, z: -0.0301} m_LocalScale: {x: 0.436, y: 0.436, z: 0.436} @@ -7012,7 +7212,6 @@ Transform: - {fileID: 4000011206878738} - {fileID: 4000011225904734} m_Father: {fileID: 473678} - m_RootOrder: 14 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000010882293456 MeshFilter: @@ -7072,9 +7271,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000011622452938} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1.12, y: 0.73, z: 0.1} m_Center: {x: 0, y: 0, z: 0} --- !u!114 &114000011006960986 @@ -7150,6 +7357,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000011692107830} + serializedVersion: 2 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} @@ -7158,7 +7366,6 @@ Transform: - {fileID: 4000010769280002} - {fileID: 4000012312614358} m_Father: {fileID: 4000013760615668} - m_RootOrder: 3 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &1000011797134698 GameObject: @@ -7185,13 +7392,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000011797134698} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0.5, z: -0.0025} m_LocalScale: {x: 1, y: 0.02857143, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000014044617982} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000011351091714 MeshFilter: @@ -7267,6 +7474,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000011835935838} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0.24, y: 0, z: -0.1} m_LocalScale: {x: 1, y: 1, z: 1} @@ -7276,7 +7484,6 @@ Transform: - {fileID: 4000010399852960} - {fileID: 4000013175241986} m_Father: {fileID: 473678} - m_RootOrder: 35 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!23 &23000010716088472 MeshRenderer: @@ -7347,13 +7554,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000012110338046} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0.3, y: -0.25, z: -0.05} m_LocalScale: {x: 0.55, y: 0.55, z: 0.35} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 461906} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000012807620068 MeshFilter: @@ -7413,9 +7620,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000012110338046} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 0.7, y: 1, z: 0.025} m_Center: {x: 0, y: 0, z: 0} --- !u!114 &114866655278054368 @@ -7492,13 +7707,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000012149669276} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: -0.49999997, z: 0.00228548} m_LocalScale: {x: 1, y: 0.028571434, z: 0.9142854} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000011225904734} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000010883985424 MeshFilter: @@ -7575,13 +7790,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000012311522496} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: -0.5, z: -0.0024999883} m_LocalScale: {x: 1, y: 0.028571432, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000014044617982} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000012851111020 MeshFilter: @@ -7658,6 +7873,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000012495519762} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: -0.7071068, w: 0.7071067} m_LocalPosition: {x: 0, y: 0.35714287, z: 0.002285719} m_LocalScale: {x: 1.7142856, y: 1, z: 1} @@ -7666,7 +7882,6 @@ Transform: - {fileID: 4000012956736620} - {fileID: 4000010013684490} m_Father: {fileID: 4000010470004098} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000013472049802 MeshFilter: @@ -7745,13 +7960,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000012517480522} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0.3, y: -0.25, z: -0.05} m_LocalScale: {x: 0.55, y: 0.55, z: 0.35} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 408880} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000013108224718 MeshFilter: @@ -7811,9 +8026,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000012517480522} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 0.7, y: 1, z: 0.025} m_Center: {x: 0, y: 0, z: 0} --- !u!114 &114323545490698212 @@ -7889,6 +8112,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000012586849750} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0.24000001, y: 0, z: -0.1} m_LocalScale: {x: 1, y: 1, z: 1} @@ -7897,7 +8121,6 @@ Transform: - {fileID: 6005845494309965052} - {fileID: 4000013868811186} m_Father: {fileID: 473678} - m_RootOrder: 39 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!23 &23000010319935078 MeshRenderer: @@ -7973,7 +8196,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000010586237508} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} @@ -8181,13 +8403,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000012646663936} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0.3, y: -0.25, z: -0.05} m_LocalScale: {x: 0.55, y: 0.55, z: 0.35} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 493402} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000010800557860 MeshFilter: @@ -8247,9 +8469,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000012646663936} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 0.7, y: 1, z: 0.025} m_Center: {x: 0, y: 0, z: 0} --- !u!114 &114549399520814884 @@ -8328,13 +8558,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000012671655106} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0.4113, y: -0.4082, z: -0.05} m_LocalScale: {x: 0.26, y: 0.26, z: 0.55} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 411214} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000013219408624 MeshFilter: @@ -8394,9 +8624,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000012671655106} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 0.7, y: 1, z: 0.025} m_Center: {x: 0, y: 0, z: 0} --- !u!114 &114871902584000098 @@ -8474,13 +8712,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000012741200280} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: -0.337, z: -0.025} m_LocalScale: {x: 0.45, y: 0.45, z: 0.45} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000012758470188} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000010754946242 MeshFilter: @@ -8572,13 +8810,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000012752427380} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0.3, y: -0.25, z: -0.05} m_LocalScale: {x: 0.55, y: 0.55, z: 0.35} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 406124} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000013646666634 MeshFilter: @@ -8638,9 +8876,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000012752427380} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 0.7, y: 1, z: 0.025} m_Center: {x: 0, y: 0, z: 0} --- !u!114 &114362806798608418 @@ -8717,13 +8963,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000012812392858} + serializedVersion: 2 m_LocalRotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071067} m_LocalPosition: {x: -0, y: 0, z: 0} m_LocalScale: {x: 100, y: 100, z: 100} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000013868811186} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000012714006372 MeshFilter: @@ -8809,7 +9055,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000012758470188} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} @@ -9037,13 +9282,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000013014429140} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0.3, y: -0.25, z: -0.05} m_LocalScale: {x: 0.55, y: 0.55, z: 0.35} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 474082} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000011491718626 MeshFilter: @@ -9103,9 +9348,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000013014429140} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 0.7, y: 1, z: 0.025} m_Center: {x: 0, y: 0, z: 0} --- !u!114 &114195161851537796 @@ -9182,13 +9435,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000013171469736} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0.49999997, z: 0.0022855483} m_LocalScale: {x: 1, y: 0.028571434, z: 0.9142854} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000011225904734} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000010406950982 MeshFilter: @@ -9266,13 +9519,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000013208288780} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0.05999999} m_LocalScale: {x: 2, y: 1, z: 0.8783332} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000010586237508} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000012686066634 MeshFilter: @@ -9290,9 +9543,17 @@ MeshCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000013208288780} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 4 + serializedVersion: 5 m_Convex: 0 m_CookingOptions: 30 m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} @@ -9363,13 +9624,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000013281891730} + serializedVersion: 2 m_LocalRotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071067} m_LocalPosition: {x: -0, y: 0, z: 0} m_LocalScale: {x: 100, y: 100, z: 100} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000012925136122} - m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000010839572548 MeshFilter: @@ -9446,6 +9707,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000013345196914} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: -0.7071068, w: 0.7071067} m_LocalPosition: {x: 0, y: -1.0697142, z: 0.9165714} m_LocalScale: {x: 4.5714283, y: 1, z: 1} @@ -9454,7 +9716,6 @@ Transform: - {fileID: 4000013753592404} - {fileID: 4000013563491830} m_Father: {fileID: 4000010470004098} - m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000010676958356 MeshFilter: @@ -9529,6 +9790,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000013409032268} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0.000000014901161, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} @@ -9537,7 +9799,6 @@ Transform: - {fileID: 4000012486041186} - {fileID: 4000013191658744} m_Father: {fileID: 4000012758470188} - m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &1000013456164478 GameObject: @@ -9564,13 +9825,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000013456164478} + serializedVersion: 2 m_LocalRotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071067} m_LocalPosition: {x: -0, y: 0, z: 0} m_LocalScale: {x: 100, y: 100, z: 100} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000013175241986} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000013506293760 MeshFilter: @@ -9649,13 +9910,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000013560234246} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0.3, y: -0.25, z: -0.05} m_LocalScale: {x: 0.55, y: 0.55, z: 0.35} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 401916} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000012247514248 MeshFilter: @@ -9715,9 +9976,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000013560234246} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 0.7, y: 1, z: 0.025} m_Center: {x: 0, y: 0, z: 0} --- !u!114 &114244469609186990 @@ -9796,13 +10065,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000013664674502} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0.3, y: -0.25, z: -0.05} m_LocalScale: {x: 0.55, y: 0.55, z: 0.35} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 473330} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000012106556998 MeshFilter: @@ -9862,9 +10131,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000013664674502} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 0.7, y: 1, z: 0.025} m_Center: {x: 0, y: 0, z: 0} --- !u!114 &114635763778407954 @@ -9943,6 +10220,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000013782811050} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: -0.44, z: -0.054} m_LocalScale: {x: 0.29999998, y: 0.29999998, z: 0.29999998} @@ -9951,7 +10229,6 @@ Transform: - {fileID: 2996170910482353195} - {fileID: 4000012865260200} m_Father: {fileID: 4000013760615668} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000013863582604 MeshFilter: @@ -10011,9 +10288,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000013782811050} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 2, y: 1, z: 0.01} m_Center: {x: 0, y: 0, z: 0} --- !u!114 &114000010491166222 @@ -10119,13 +10404,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000013804988808} + serializedVersion: 2 m_LocalRotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071067} m_LocalPosition: {x: -0, y: 0, z: 0} m_LocalScale: {x: 100, y: 100, z: 100} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000012925136122} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000011914095804 MeshFilter: @@ -10202,13 +10487,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1000013953183086} + serializedVersion: 2 m_LocalRotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071067} m_LocalPosition: {x: -0, y: 0, z: 0} m_LocalScale: {x: 100, y: 100, z: 100} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000013454894384} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33000014113340520 MeshFilter: @@ -10285,13 +10570,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1003691897808460} + serializedVersion: 2 m_LocalRotation: {x: -0, y: 0.7073474, z: 0.7068661, w: 0} m_LocalPosition: {x: 0, y: 0, z: 0.01} m_LocalScale: {x: 95.2381, y: 100, z: 40.000046} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4604395735417884} - m_RootOrder: 2 m_LocalEulerAnglesHint: {x: -89.961006, y: 180, z: 0} --- !u!33 &33682943879407966 MeshFilter: @@ -10368,13 +10653,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1023390386316022} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: -0.29999998, y: -0.2999997, z: -0.04} m_LocalScale: {x: 0.29999998, y: 0.29999998, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 474082} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33767155316608232 MeshFilter: @@ -10451,13 +10736,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1037653607876102} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: -0.30000007, y: -0.29999998, z: -0.04} m_LocalScale: {x: 0.29999998, y: 0.29999998, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000010333377928} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33256049024245930 MeshFilter: @@ -10541,7 +10826,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4405259647245308} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} @@ -10749,13 +11033,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1063686457530790} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: -0.30000007, y: -0.3, z: -0.04} m_LocalScale: {x: 0.29999998, y: 0.29999998, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 493402} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33405629311793028 MeshFilter: @@ -10832,13 +11116,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1122766985615510} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: -0.30000007, y: -0.2999997, z: -0.04} m_LocalScale: {x: 0.29999998, y: 0.29999998, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 461906} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33373790172941974 MeshFilter: @@ -10914,6 +11198,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1147890328312932} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0.24, y: 0, z: -0.1} m_LocalScale: {x: 1, y: 1, z: 1} @@ -10922,7 +11207,6 @@ Transform: - {fileID: 224259994149328172} - {fileID: 4299097812957920} m_Father: {fileID: 473678} - m_RootOrder: 36 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!23 &23762962104057700 MeshRenderer: @@ -10991,13 +11275,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1157290024452308} + serializedVersion: 2 m_LocalRotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071067} m_LocalPosition: {x: -0, y: 0, z: 0} m_LocalScale: {x: 100, y: 100, z: 100} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4299097812957920} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33340641278957148 MeshFilter: @@ -11081,7 +11365,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4227232315394708} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} @@ -11287,13 +11570,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1194264369200220} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: -0.30000025, y: -0.29999998, z: -0.04} m_LocalScale: {x: 0.29999998, y: 0.29999998, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 476782} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33315681194821888 MeshFilter: @@ -11372,6 +11655,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1227842993942742} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: -1.65, y: 0, z: 0} m_LocalScale: {x: 1.05, y: 2.5, z: 1} @@ -11382,7 +11666,6 @@ Transform: - {fileID: 4160166080439610} - {fileID: 4088058456074744} m_Father: {fileID: 473678} - m_RootOrder: 41 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!65 &65181151135621986 BoxCollider: @@ -11392,9 +11675,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1227842993942742} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1, y: 1, z: 0.02} m_Center: {x: 0, y: 0, z: 0} --- !u!33 &33728303746786244 @@ -11552,13 +11843,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1236945777315276} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: -0.29999998, y: -0.3, z: -0.04} m_LocalScale: {x: 0.29999998, y: 0.29999998, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 401916} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33461801393607834 MeshFilter: @@ -11635,13 +11926,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1329085538968134} + serializedVersion: 2 m_LocalRotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071067} m_LocalPosition: {x: -0, y: 0, z: 0} m_LocalScale: {x: 100, y: 100, z: 100} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4572210679967688} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33281479349217826 MeshFilter: @@ -11718,13 +12009,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1336920247228296} + serializedVersion: 2 m_LocalRotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071067} m_LocalPosition: {x: -0, y: 0, z: 0} m_LocalScale: {x: 100, y: 100, z: 100} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4299097812957920} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33306568108413466 MeshFilter: @@ -11801,13 +12092,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1352538921561852} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 0.65, y: 0.65, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4653590090589872} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33291731134228232 MeshFilter: @@ -11885,13 +12176,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1353537369857522} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: -0.30000004, y: -0.30000004, z: -0.04} m_LocalScale: {x: 0.3, y: 0.3, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 411214} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33552357186652048 MeshFilter: @@ -11909,9 +12200,17 @@ MeshCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1353537369857522} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 4 + serializedVersion: 5 m_Convex: 0 m_CookingOptions: 30 m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} @@ -11982,13 +12281,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1357195914620088} + serializedVersion: 2 m_LocalRotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071067} m_LocalPosition: {x: -0, y: 0, z: 0} m_LocalScale: {x: 100, y: 100, z: 100} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4572210679967688} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33408476018355782 MeshFilter: @@ -12073,7 +12372,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4405002968423422} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} @@ -12292,13 +12590,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1585279513007384} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 2, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4227232315394708} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33595363077444256 MeshFilter: @@ -12375,13 +12673,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1593948112818424} + serializedVersion: 2 m_LocalRotation: {x: -0.7068661, y: 0, z: 0, w: 0.7073474} m_LocalPosition: {x: 0.00000011353266, y: 0, z: 0.005} m_LocalScale: {x: 95.2381, y: 100.000046, z: 40.000057} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4604395735417884} - m_RootOrder: 3 m_LocalEulerAnglesHint: {x: -89.961006, y: 0, z: 0} --- !u!33 &33685971061773632 MeshFilter: @@ -12460,6 +12758,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1631327297680716} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: -0.44, z: -0.054000005} m_LocalScale: {x: 0.29999998, y: 0.29999998, z: 0.29999998} @@ -12468,7 +12767,6 @@ Transform: - {fileID: 8468573391107282333} - {fileID: 4483479252455118} m_Father: {fileID: 4405259647245308} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33174227262776470 MeshFilter: @@ -12606,9 +12904,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1631327297680716} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 2, y: 1.0000001, z: 0.1} m_Center: {x: 0, y: 0, z: 0} --- !u!1 &1637582873204310 @@ -12636,13 +12942,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1637582873204310} + serializedVersion: 2 m_LocalRotation: {x: -0.7071068, y: -0, z: -0, w: 0.7071067} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 95.2381, y: 99.99982, z: 39.999924} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4604395735417884} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33530010535052012 MeshFilter: @@ -12720,13 +13026,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1644973727690454} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0.847, y: 1.001, z: -0.05} m_LocalScale: {x: 0.4, y: 0.4, z: 0.4} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 473678} - m_RootOrder: 26 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33567874645767864 MeshFilter: @@ -12814,6 +13120,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1672029381864338} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0.000000014901161, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} @@ -12822,7 +13129,6 @@ Transform: - {fileID: 4776209461862024} - {fileID: 4299019526169640} m_Father: {fileID: 4405002968423422} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &1676764474539712 GameObject: @@ -12848,6 +13154,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1676764474539712} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0.24, y: 0, z: -0.1} m_LocalScale: {x: 1, y: 1, z: 1} @@ -12857,7 +13164,6 @@ Transform: - {fileID: 4227232315394708} - {fileID: 4572210679967688} m_Father: {fileID: 473678} - m_RootOrder: 37 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!23 &23211508628126822 MeshRenderer: @@ -12933,7 +13239,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4000011114460008} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} @@ -13147,13 +13452,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1718400279081948} + serializedVersion: 2 m_LocalRotation: {x: 0.7071068, y: -0, z: -0, w: 0.7071068} m_LocalPosition: {x: 0, y: 0, z: 0.025} m_LocalScale: {x: 0.79999995, y: 0.02, z: 0.8} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4653590090589872} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 90, y: 0, z: 0} --- !u!33 &33957633259298626 MeshFilter: @@ -13230,13 +13535,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1806376406434594} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: -0.29999998, y: -0.29999998, z: -0.04} m_LocalScale: {x: 0.29999998, y: 0.29999998, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 406124} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33436210745481492 MeshFilter: @@ -13311,6 +13616,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1838418458797118} + serializedVersion: 2 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} @@ -13319,7 +13625,6 @@ Transform: - {fileID: 4434180684794314} - {fileID: 4908000352793634} m_Father: {fileID: 4405259647245308} - m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &1839306045669634 GameObject: @@ -13348,6 +13653,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1839306045669634} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 1.082, y: -1.252, z: -0.01} m_LocalScale: {x: 0.3, y: 0.3, z: 0.3} @@ -13356,7 +13662,6 @@ Transform: - {fileID: 4594768142946388} - {fileID: 4485662548378186} m_Father: {fileID: 473678} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33573308757238834 MeshFilter: @@ -13416,9 +13721,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1839306045669634} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1.0000001, y: 1, z: 0.01} m_Center: {x: 0, y: 0, z: -0.01} --- !u!114 &114786666466332882 @@ -13518,7 +13831,7 @@ GameObject: m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 - m_IsActive: 0 + m_IsActive: 1 --- !u!4 &4459060226476560 Transform: m_ObjectHideFlags: 0 @@ -13526,13 +13839,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1842065821143492} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: -0.839, y: 1.013, z: -0.0311} m_LocalScale: {x: 0.25, y: 0.25, z: 0.25} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 473678} - m_RootOrder: 24 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33422040586648110 MeshFilter: @@ -13592,9 +13905,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1842065821143492} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1.0000001, y: 1.0000001, z: 0.1} m_Center: {x: 0, y: 0, z: 0} --- !u!114 &114501524827504004 @@ -13633,7 +13954,7 @@ MonoBehaviour: m_LocalVariables: [] m_DescriptionActivateSpeed: 12 m_DescriptionZScale: 1 - m_ButtonTexture: {fileID: 2800000, guid: da8fcd82368826b4cad505e8249bd63c, type: 3} + m_ButtonTexture: {fileID: 2800000, guid: ca2b2689a21743448be1a5306c61e90b, type: 3} m_AtlasTexture: 1 m_ToggleButton: 0 m_LongPressReleaseButton: 0 @@ -13700,13 +14021,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1855919676530468} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: -0.29999998, y: -0.3, z: -0.04} m_LocalScale: {x: 0.29999998, y: 0.29999998, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 408880} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33999473819885868 MeshFilter: @@ -13783,13 +14104,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1914095689519454} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: -0.29999998, y: -0.29999998, z: -0.04} m_LocalScale: {x: 0.29999998, y: 0.29999998, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 473330} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &33810070024719510 MeshFilter: @@ -13868,13 +14189,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 894190226255371916} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0.875, y: 1.03, z: -0.025} m_LocalScale: {x: 0.175, y: 0.175, z: 0.175} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 473678} - m_RootOrder: 31 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &9181308231173954030 MeshFilter: @@ -13934,9 +14255,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 894190226255371916} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1.0000001, y: 1.0000001, z: 0.1} m_Center: {x: 0, y: 0, z: 0} --- !u!114 &4188583716324234656 @@ -14040,6 +14369,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 915226954648437342} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0.000000014901161, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} @@ -14048,7 +14378,6 @@ Transform: - {fileID: 7463230845054887281} - {fileID: 3442742383225157293} m_Father: {fileID: 9117108218266893509} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &1322492417976703408 GameObject: @@ -14075,13 +14404,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1322492417976703408} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: -0.5, z: -0.0024999883} m_LocalScale: {x: 1, y: 0.028571432, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 8668434879085770626} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &2500334484848516744 MeshFilter: @@ -14165,7 +14494,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 1524240171334712824} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} @@ -14373,6 +14701,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 2158335996185070942} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: -0.7071068, w: 0.7071067} m_LocalPosition: {x: 0, y: -1.0697142, z: 0.9165714} m_LocalScale: {x: 4.5714283, y: 1, z: 1} @@ -14381,7 +14710,6 @@ Transform: - {fileID: 8835613076674131173} - {fileID: 1681593874138847941} m_Father: {fileID: 7687396309078903398} - m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &1248259070182587467 MeshFilter: @@ -14456,6 +14784,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 2316682789993501927} + serializedVersion: 2 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} @@ -14464,7 +14793,6 @@ Transform: - {fileID: 1126899405721930507} - {fileID: 2349666135276550853} m_Father: {fileID: 1524240171334712824} - m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &2564330845180575454 GameObject: @@ -14491,13 +14819,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 2564330845180575454} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 2, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 3702262655533381092} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &3786255149657314558 MeshFilter: @@ -14581,7 +14909,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 9117108218266893509} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} @@ -14789,6 +15116,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 3489518439063806035} + serializedVersion: 2 m_LocalRotation: {x: 0.5000001, y: 0.5, z: -0.5, w: 0.49999994} m_LocalPosition: {x: 0, y: 1.2142847, z: 0.4594286} m_LocalScale: {x: 0.9142857, y: 1, z: 1} @@ -14797,7 +15125,6 @@ Transform: - {fileID: 321097991674213930} - {fileID: 6474380007388265344} m_Father: {fileID: 7687396309078903398} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &3710666160644817266 MeshFilter: @@ -14874,13 +15201,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 3711792098476514597} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0.5, z: -0.0025} m_LocalScale: {x: 1, y: 0.02857143, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 8668434879085770626} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &6232630873404181854 MeshFilter: @@ -14956,6 +15283,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 4374687820491222719} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0.24000001, y: 0, z: -0.1} m_LocalScale: {x: 1, y: 1, z: 1} @@ -14964,7 +15292,6 @@ Transform: - {fileID: 5273980064973361335} - {fileID: 6471389067300543686} m_Father: {fileID: 473678} - m_RootOrder: 40 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!23 &3762244675612984118 MeshRenderer: @@ -15040,7 +15367,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 3702262655533381092} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} @@ -15246,13 +15572,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 4778719595247149710} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0.49999997, z: -0.002} m_LocalScale: {x: 1, y: 0.028571434, z: 2} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 550194924522150295} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &6533685272076450346 MeshFilter: @@ -15330,13 +15656,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 4987445825603729169} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: -0.7071068, w: 0.7071068} m_LocalPosition: {x: 0.847, y: 1.001, z: -0.05} m_LocalScale: {x: 0.25, y: 0.25, z: 0.25} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 473678} - m_RootOrder: 27 m_LocalEulerAnglesHint: {x: 0, y: 0, z: -90} --- !u!33 &2139868953206300193 MeshFilter: @@ -15425,13 +15751,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 5708433634109880750} + serializedVersion: 2 m_LocalRotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071067} m_LocalPosition: {x: -0, y: 0, z: 0} m_LocalScale: {x: 100, y: 100, z: 100} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 6471389067300543686} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &7528090674439679421 MeshFilter: @@ -15514,7 +15840,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 473678} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} @@ -15646,7 +15971,7 @@ MonoBehaviour: m_VertexBufferAutoSizeReduction: 1 m_useMaxVisibleDescender: 1 m_pageToDisplay: 1 - m_margin: {x: 0, y: 0, z: -0.5816542, w: 0} + m_margin: {x: 0, y: 0, z: -0.91909444, w: 0} m_isUsingLegacyAnimationComponent: 0 m_isVolumetricText: 0 _SortingLayer: 0 @@ -15679,6 +16004,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 6839353153389732464} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0.24000001, y: 0, z: -0.1} m_LocalScale: {x: 1, y: 1, z: 1} @@ -15688,7 +16014,6 @@ Transform: - {fileID: 3702262655533381092} - {fileID: 1817565260503090077} m_Father: {fileID: 473678} - m_RootOrder: 38 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!23 &2320526944858906914 MeshRenderer: @@ -15759,13 +16084,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 6937020573975178444} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0.875, y: 1.03, z: -0.025} m_LocalScale: {x: 0.175, y: 0.175, z: 0.175} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 473678} - m_RootOrder: 29 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &2502232274484467176 MeshFilter: @@ -15825,9 +16150,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 6937020573975178444} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1.0000001, y: 1.0000001, z: 0.1} m_Center: {x: 0, y: 0, z: 0} --- !u!114 &6670325552642882511 @@ -15933,13 +16266,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 6967533768856939298} + serializedVersion: 2 m_LocalRotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071067} m_LocalPosition: {x: -0, y: 0, z: 0} m_LocalScale: {x: 100, y: 100, z: 100} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 6471389067300543686} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &7509040775308887635 MeshFilter: @@ -16018,13 +16351,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 7072846544151351213} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0.875, y: 1.03, z: -0.025} m_LocalScale: {x: 0.175, y: 0.175, z: 0.175} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 473678} - m_RootOrder: 30 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &7617378168068650857 MeshFilter: @@ -16084,9 +16417,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 7072846544151351213} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1.0000001, y: 1.0000001, z: 0.1} m_Center: {x: 0, y: 0, z: 0} --- !u!114 &7544911188538389732 @@ -16199,7 +16540,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 473678} - m_RootOrder: 32 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} @@ -16407,13 +16747,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 7514244858002170337} + serializedVersion: 2 m_LocalRotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071067} m_LocalPosition: {x: -0, y: 0, z: 0} m_LocalScale: {x: 100, y: 100, z: 100} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 1817565260503090077} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &2312766600907746419 MeshFilter: @@ -16492,6 +16832,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 7675354702135526188} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: -0.44, z: -0.054000005} m_LocalScale: {x: 0.29999998, y: 0.29999998, z: 0.29999998} @@ -16500,7 +16841,6 @@ Transform: - {fileID: 863212687757741380} - {fileID: 6818748104769445831} m_Father: {fileID: 1524240171334712824} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &6394529472826107509 MeshFilter: @@ -16638,9 +16978,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 7675354702135526188} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 2, y: 1.0000001, z: 0.1} m_Center: {x: 0, y: 0, z: 0} --- !u!1 &7809439681076855981 @@ -16675,7 +17023,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 4604395735417884} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} @@ -16883,6 +17230,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 8051552516459751659} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: -0.84, y: -0.4779, z: -0.0301} m_LocalScale: {x: 0.43600002, y: 0.43600002, z: 0.43600002} @@ -16892,7 +17240,6 @@ Transform: - {fileID: 550194924522150295} - {fileID: 8773122714945324681} m_Father: {fileID: 473678} - m_RootOrder: 16 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &2565729595090453201 MeshFilter: @@ -16952,9 +17299,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 8051552516459751659} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1.12, y: 0.73, z: 0.1} m_Center: {x: 0, y: 0, z: 0} --- !u!114 &4985083439257374453 @@ -17032,13 +17387,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 8156343948566993514} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: -0.49999997, z: 0.00228548} m_LocalScale: {x: 1, y: 0.028571434, z: 0.9142854} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 8773122714945324681} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &7850102019527573647 MeshFilter: @@ -17115,13 +17470,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 8334431517929914044} + serializedVersion: 2 m_LocalRotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071067} m_LocalPosition: {x: -0, y: 0, z: 0} m_LocalScale: {x: 100, y: 100, z: 100} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 1817565260503090077} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &1779665805953307883 MeshFilter: @@ -17198,13 +17553,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 8425099743687099145} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: -0.49999997, z: -0.002} m_LocalScale: {x: 1, y: 0.028571434, z: 2} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 550194924522150295} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &5384255025845176638 MeshFilter: @@ -17283,13 +17638,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 8515080880137723669} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0.922, y: 0.956, z: -0.075} m_LocalScale: {x: 0.1, y: 0.1, z: 0.1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 473678} - m_RootOrder: 28 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &830589215893783279 MeshFilter: @@ -17349,9 +17704,17 @@ BoxCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 8515080880137723669} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 2.75, y: 2.75, z: 0.1} m_Center: {x: -0.75, y: 0.5, z: 0} --- !u!114 &5055648481581678162 @@ -17457,6 +17820,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 8643510522094066947} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: -0.7071068, w: 0.7071067} m_LocalPosition: {x: 0, y: 0.35714287, z: 0.002285719} m_LocalScale: {x: 1.7142856, y: 1, z: 1} @@ -17465,7 +17829,6 @@ Transform: - {fileID: 8235492235284656829} - {fileID: 5169543984843292650} m_Father: {fileID: 7687396309078903398} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &3909138286404281281 MeshFilter: @@ -17549,7 +17912,6 @@ RectTransform: m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 473678} - m_RootOrder: 33 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} @@ -17759,13 +18121,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 8955674742366199644} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0.49999997, z: 0.0022855483} m_LocalScale: {x: 1, y: 0.028571434, z: 0.9142854} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 8773122714945324681} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &870282709681677666 MeshFilter: diff --git a/Assets/Prefabs/PopUps/PopUpWindow_Accounts.prefab b/Assets/Prefabs/PopUps/PopUpWindow_Accounts.prefab index dc05d48064..8a49196286 100644 --- a/Assets/Prefabs/PopUps/PopUpWindow_Accounts.prefab +++ b/Assets/Prefabs/PopUps/PopUpWindow_Accounts.prefab @@ -1,5 +1,40 @@ %YAML 1.1 %TAG !u! tag:unity3d.com,2011: +--- !u!1 &162347472523419310 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 8994260351568061772} + m_Layer: 16 + m_Name: Icosa_SignedInElements + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &8994260351568061772 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 162347472523419310} + serializedVersion: 2 + 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_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 3716870166160541890} + - {fileID: 9214833072643761372} + - {fileID: 2434770951962534735} + - {fileID: 5914045499585322770} + m_Father: {fileID: 7706333168622570552} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &217738510970157188 GameObject: m_ObjectHideFlags: 0 @@ -25,13 +60,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 217738510970157188} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0.37, y: -0.324, z: -0.025} m_LocalScale: {x: 0.4, y: 0.4, z: 0.4} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 8645625732761162234} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &597686372283234627 MeshFilter: @@ -83,6 +118,177 @@ MeshRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_AdditionalVertexStreams: {fileID: 0} +--- !u!1 &237032865188240432 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 96286366463442578} + - component: {fileID: 9096299298168311087} + - component: {fileID: 4903674468560392015} + m_Layer: 16 + m_Name: Icosa_Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &96286366463442578 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 237032865188240432} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: -0.01} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1000721931266647293} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0.428, y: 0.3524501} + m_SizeDelta: {x: 20, y: 5} + m_Pivot: {x: 0, y: 1} +--- !u!23 &9096299298168311087 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 237032865188240432} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + 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 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!114 &4903674468560392015 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 237032865188240432} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 9541d86e2fd84c1d9990edf0852d74ab, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_text: Icosa + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} + m_sharedMaterial: {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4294967295 + m_fontColor: {r: 1, g: 1, b: 1, a: 1} + m_enableVertexGradient: 0 + m_colorMode: 3 + m_fontColorGradient: + topLeft: {r: 1, g: 1, b: 1, a: 1} + topRight: {r: 1, g: 1, b: 1, a: 1} + bottomLeft: {r: 1, g: 1, b: 1, a: 1} + bottomRight: {r: 1, g: 1, b: 1, a: 1} + m_fontColorGradientPreset: {fileID: 0} + m_spriteAsset: {fileID: 0} + m_tintAllSprites: 0 + m_StyleSheet: {fileID: 0} + m_TextStyleHashCode: -1183493901 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_fontSize: 1.35 + m_fontSizeBase: 1.35 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_HorizontalAlignment: 1 + m_VerticalAlignment: 256 + m_textAlignment: 65535 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_enableWordWrapping: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 0 + m_isCullingEnabled: 0 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_IsTextObjectScaleStatic: 0 + m_VertexBufferAutoSizeReduction: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + _SortingLayer: 0 + _SortingLayerID: 0 + _SortingOrder: 0 + m_hasFontAssetChanged: 0 + m_renderer: {fileID: 9096299298168311087} + m_maskType: 0 --- !u!1 &271835898861049686 GameObject: m_ObjectHideFlags: 0 @@ -108,6 +314,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 271835898861049686} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0.621, y: 0.11, z: -0.010000025} m_LocalScale: {x: 0.4, y: 0.4, z: 0.4} @@ -116,7 +323,6 @@ Transform: - {fileID: 3392034205142368857} - {fileID: 6661346418304443125} m_Father: {fileID: 529827201699571093} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!33 &1135707697623452651 MeshFilter: @@ -168,7 +374,7 @@ MeshRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!1 &440723707841846920 +--- !u!1 &281059589699444468 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -176,48 +382,46 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 4590447671262214820} - - component: {fileID: 2121377069448007116} - - component: {fileID: 1795340145885663930} - - component: {fileID: 2756793802573776306} - - component: {fileID: 3740906181516385311} + - component: {fileID: 282387889154546380} + - component: {fileID: 256765526658491878} + - component: {fileID: 267047011047381474} m_Layer: 16 - m_Name: Google_Cancel + m_Name: PopupBg m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!4 &4590447671262214820 +--- !u!4 &282387889154546380 Transform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 440723707841846920} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: -0.845, y: -0.242, z: -0.06} - m_LocalScale: {x: 0.35, y: 0.35, z: 0.35} + m_GameObject: {fileID: 281059589699444468} + serializedVersion: 2 + m_LocalRotation: {x: -0.7071068, y: -0, z: -0, w: 0.7071067} + m_LocalPosition: {x: 0, y: 0.09399994, z: 0.000999992} + m_LocalScale: {x: 88.50999, y: 88.51, z: 88.51} m_ConstrainProportionsScale: 0 m_Children: [] - m_Father: {fileID: 7741920746089690377} - m_RootOrder: 3 + m_Father: {fileID: 282387885870267606} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!33 &2121377069448007116 +--- !u!33 &256765526658491878 MeshFilter: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 440723707841846920} - m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} ---- !u!23 &1795340145885663930 + m_GameObject: {fileID: 281059589699444468} + m_Mesh: {fileID: 4300002, guid: 3efe5b86b55995545a231ce66a53b402, type: 3} +--- !u!23 &267047011047381474 MeshRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 440723707841846920} + m_GameObject: {fileID: 281059589699444468} m_Enabled: 1 m_CastShadows: 0 m_ReceiveShadows: 0 @@ -231,7 +435,7 @@ MeshRenderer: m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 2100000, guid: 40d29de2bdc11f04dbfa25059165916e, type: 2} + - {fileID: 2100000, guid: db0305ff9081c3b448ac79e85d26e5d4, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 @@ -240,7 +444,7 @@ MeshRenderer: m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 m_ReceiveGI: 1 - m_PreserveUVs: 1 + m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 m_StitchLightmapSeams: 0 @@ -253,153 +457,75 @@ MeshRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!114 &2756793802573776306 -MonoBehaviour: +--- !u!1 &281059592884163862 +GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 440723707841846920} + serializedVersion: 6 + m_Component: + - component: {fileID: 282387885870267606} + - component: {fileID: 217270776815681370} + - component: {fileID: 3134156942944013523} + - component: {fileID: 7526589234644902223} + m_Layer: 16 + m_Name: Icosa_LoginElements + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &282387885870267606 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 281059592884163862} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0.67, y: 0.39, z: -0.212} + m_LocalScale: {x: 1.5, y: 1.4999999, z: 1.4999999} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 3194813434804236579} + - {fileID: 282387889154546380} + - {fileID: 282387882118496818} + - {fileID: 8121802616684643442} + m_Father: {fileID: 7706333168622570552} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!65 &217270776815681370 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 281059592884163862} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fc12adcafa62a22458e635d2ee7e78b5, type: 3} - m_Name: - m_EditorClassIdentifier: - m_DescriptionType: 0 - m_DescriptionYOffset: 0 - m_DescriptionText: POPUP_ACCOUNTS_CANCEL_BUTTON_DESCRIPTION - m_LocalizedDescription: - m_TableReference: - m_TableCollectionName: GUID:c84355079ab3f3e4f8f3812258805f86 - m_TableEntryReference: - m_KeyId: 15526523405381632 - m_Key: - m_FallbackState: 0 - m_WaitForCompletion: 0 - m_LocalVariables: [] - m_DescriptionTextExtra: - m_LocalizedDescriptionExtra: - m_TableReference: - m_TableCollectionName: - m_TableEntryReference: - m_KeyId: 0 - m_Key: - m_FallbackState: 0 - m_WaitForCompletion: 0 - m_LocalVariables: [] - m_DescriptionActivateSpeed: 12 - m_DescriptionZScale: 1 - m_ButtonTexture: {fileID: 2800000, guid: 957f69e59565cd1469fa095b415fa513, type: 3} - m_AtlasTexture: 0 - m_ToggleButton: 0 - m_LongPressReleaseButton: 0 - m_ButtonHasPressedAudio: 1 - m_ZAdjustHover: -0.02 - m_ZAdjustClick: 0.05 - m_HoverScale: 1.1 - m_HoverBoxColliderGrow: 0.2 - m_AddOverlay: 0 - m_Command: 0 - m_CommandParam: 1 - m_CommandParam2: -1 - m_RequiresPopup: 0 - m_CenterPopupOnButton: 0 - m_PopupOffset: {x: 0, y: 0, z: 0} - m_PopupText: - m_LocalizedPopup: - m_TableReference: - m_TableCollectionName: - m_TableEntryReference: - m_KeyId: 0 - m_Key: - m_FallbackState: 0 - m_WaitForCompletion: 0 - m_LocalVariables: [] - m_ToggleOnDescription: - m_LocalizedToggleOnDescription: - m_TableReference: - m_TableCollectionName: - m_TableEntryReference: - m_KeyId: 0 - m_Key: - m_FallbackState: 0 - m_WaitForCompletion: 0 - m_LocalVariables: [] - m_ToggleOnTexture: {fileID: 0} - m_AllowUnavailable: 0 - m_LinkedUIObject: {fileID: 0} - m_CommandIgnored: 1 - references: - version: 2 - RefIds: [] ---- !u!65 &3740906181516385311 -BoxCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 440723707841846920} - m_Material: {fileID: 0} - m_IsTrigger: 0 - m_Enabled: 1 - serializedVersion: 2 - m_Size: {x: 1, y: 1.0000001, z: 0.1} - m_Center: {x: 0, y: 0, z: -0.01} ---- !u!1 &710086474055226122 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 7893921961113671483} - - component: {fileID: 8398224192364770992} - - component: {fileID: 5384180884118313375} - - component: {fileID: 1573872792934989801} - - component: {fileID: 1569796081246134525} - m_Layer: 16 - m_Name: Google_SignIn - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &7893921961113671483 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 710086474055226122} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: -0.634, y: -0.242, z: -0.06} - m_LocalScale: {x: 0.4, y: 0.4, z: 0.4} - m_ConstrainProportionsScale: 0 - m_Children: - - {fileID: 1583684570998085433} - - {fileID: 5208561973859313428} - m_Father: {fileID: 1432546188030660464} - m_RootOrder: 4 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!33 &8398224192364770992 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 710086474055226122} - m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} ---- !u!23 &5384180884118313375 + serializedVersion: 3 + m_Size: {x: 2.5, y: 1.5, z: 0.02} + m_Center: {x: 0, y: 0, z: 0.06} +--- !u!23 &3134156942944013523 MeshRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 710086474055226122} + m_GameObject: {fileID: 281059592884163862} m_Enabled: 0 - m_CastShadows: 0 - m_ReceiveShadows: 0 + m_CastShadows: 1 + m_ReceiveShadows: 1 m_DynamicOccludee: 1 m_StaticShadowCaster: 0 m_MotionVectors: 1 @@ -410,7 +536,7 @@ MeshRenderer: m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 2100000, guid: 005edae3a0d4d1243ba88ed7543cd61d, type: 2} + - {fileID: 0} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 @@ -419,10 +545,10 @@ MeshRenderer: m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 m_ReceiveGI: 1 - m_PreserveUVs: 1 + m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 - m_StitchLightmapSeams: 0 + m_StitchLightmapSeams: 1 m_SelectedEditorRenderState: 3 m_MinimumChartSize: 4 m_AutoUVMaxDistance: 0.5 @@ -432,99 +558,35 @@ MeshRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!114 &1573872792934989801 +--- !u!114 &7526589234644902223 MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 710086474055226122} + m_GameObject: {fileID: 281059592884163862} m_Enabled: 1 m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fc12adcafa62a22458e635d2ee7e78b5, type: 3} + m_Script: {fileID: 11500000, guid: 16e24e82bd0c4dcbb02c41882fb95f45, type: 3} m_Name: m_EditorClassIdentifier: - m_DescriptionType: -1 - m_DescriptionYOffset: 0 - m_DescriptionText: - m_LocalizedDescription: - m_TableReference: - m_TableCollectionName: - m_TableEntryReference: - m_KeyId: 0 - m_Key: - m_FallbackState: 0 - m_WaitForCompletion: 0 - m_LocalVariables: [] - m_DescriptionTextExtra: - m_LocalizedDescriptionExtra: - m_TableReference: - m_TableCollectionName: - m_TableEntryReference: - m_KeyId: 0 - m_Key: - m_FallbackState: 0 - m_WaitForCompletion: 0 - m_LocalVariables: [] - m_DescriptionActivateSpeed: 12 - m_DescriptionZScale: 1 - m_ButtonTexture: {fileID: 0} - m_AtlasTexture: 0 - m_ToggleButton: 0 - m_LongPressReleaseButton: 0 - m_ButtonHasPressedAudio: 1 - m_ZAdjustHover: -0.02 - m_ZAdjustClick: 0.05 - m_HoverScale: 1.1 - m_HoverBoxColliderGrow: 0.2 - m_AddOverlay: 0 - m_Command: 95 - m_CommandParam: 1 - m_CommandParam2: -1 - m_RequiresPopup: 0 - m_CenterPopupOnButton: 0 - m_PopupOffset: {x: 0, y: 0, z: 0} - m_PopupText: - m_LocalizedPopup: - m_TableReference: - m_TableCollectionName: - m_TableEntryReference: - m_KeyId: 0 - m_Key: - m_FallbackState: 0 - m_WaitForCompletion: 0 - m_LocalVariables: [] - m_ToggleOnDescription: - m_LocalizedToggleOnDescription: - m_TableReference: - m_TableCollectionName: - m_TableEntryReference: - m_KeyId: 0 - m_Key: - m_FallbackState: 0 - m_WaitForCompletion: 0 - m_LocalVariables: [] - m_ToggleOnTexture: {fileID: 0} - m_AllowUnavailable: 1 - m_LinkedUIObject: {fileID: 0} - m_CommandIgnored: 0 - references: - version: 2 - RefIds: [] ---- !u!65 &1569796081246134525 -BoxCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 710086474055226122} - m_Material: {fileID: 0} - m_IsTrigger: 0 - m_Enabled: 1 - serializedVersion: 2 - m_Size: {x: 2, y: 1.0000001, z: 0.1} - m_Center: {x: 0, y: 0, z: -0.01} ---- !u!1 &805844845446197852 + OnSubmit: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 8529915923179660036} + m_TargetAssemblyTypeName: TiltBrush.ProfilePopUpWindow, Assembly-CSharp + m_MethodName: HandleIcosaLoginSubmit + m_Mode: 0 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + InputEnabled: 1 +--- !u!1 &281059592966504990 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -532,64 +594,60 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 7338107887349877872} - - component: {fileID: 6941474665913055402} - - component: {fileID: 796423230181286760} - - component: {fileID: 422651024943017319} - - component: {fileID: 5581805715966274588} - m_Layer: 14 - m_Name: ConfirmationButton + - component: {fileID: 282387882118496818} + - component: {fileID: 256765527167650962} + - component: {fileID: 267047009147745160} + m_Layer: 16 + m_Name: PopupBorder m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!4 &7338107887349877872 +--- !u!4 &282387882118496818 Transform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 805844845446197852} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: -0.434, z: -0.08} - m_LocalScale: {x: 0.6, y: 0.29999998, z: 0.29999998} + m_GameObject: {fileID: 281059592966504990} + serializedVersion: 2 + m_LocalRotation: {x: -0.7071068, y: -0, z: -0, w: 0.7071067} + m_LocalPosition: {x: 0, y: 0.094, z: 0.001} + m_LocalScale: {x: 88.50999, y: 88.51, z: 88.51} m_ConstrainProportionsScale: 0 - m_Children: - - {fileID: 6454029799957143386} - - {fileID: 8006143071345660080} - m_Father: {fileID: 3457603883277620212} - m_RootOrder: 2 + m_Children: [] + m_Father: {fileID: 282387885870267606} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!33 &6941474665913055402 +--- !u!33 &256765527167650962 MeshFilter: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 805844845446197852} - m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} ---- !u!23 &796423230181286760 + m_GameObject: {fileID: 281059592966504990} + m_Mesh: {fileID: 4300000, guid: 3efe5b86b55995545a231ce66a53b402, type: 3} +--- !u!23 &267047009147745160 MeshRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 805844845446197852} - m_Enabled: 0 + m_GameObject: {fileID: 281059592966504990} + m_Enabled: 1 m_CastShadows: 0 m_ReceiveShadows: 0 m_DynamicOccludee: 1 m_StaticShadowCaster: 0 m_MotionVectors: 1 - m_LightProbeUsage: 0 + m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 2100000, guid: 3c8ca511828182747a0b79564892ec57, type: 2} + - {fileID: 2100000, guid: 77dd4ff8b1158a84397aba783cd0af05, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 @@ -611,162 +669,65 @@ MeshRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!65 &422651024943017319 -BoxCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 805844845446197852} - m_Material: {fileID: 0} - m_IsTrigger: 0 - m_Enabled: 1 - serializedVersion: 2 - m_Size: {x: 1, y: 1, z: 0.01} - m_Center: {x: 0, y: 0, z: -0.01} ---- !u!114 &5581805715966274588 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 805844845446197852} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fc12adcafa62a22458e635d2ee7e78b5, type: 3} - m_Name: - m_EditorClassIdentifier: - m_DescriptionType: -1 - m_DescriptionYOffset: 0 - m_DescriptionText: - m_LocalizedDescription: - m_TableReference: - m_TableCollectionName: - m_TableEntryReference: - m_KeyId: 0 - m_Key: - m_FallbackState: 0 - m_WaitForCompletion: 0 - m_LocalVariables: [] - m_DescriptionTextExtra: - m_LocalizedDescriptionExtra: - m_TableReference: - m_TableCollectionName: - m_TableEntryReference: - m_KeyId: 0 - m_Key: - m_FallbackState: 0 - m_WaitForCompletion: 0 - m_LocalVariables: [] - m_DescriptionActivateSpeed: 12 - m_DescriptionZScale: 1 - m_ButtonTexture: {fileID: 0} - m_AtlasTexture: 0 - m_ToggleButton: 0 - m_LongPressReleaseButton: 0 - m_ButtonHasPressedAudio: 1 - m_ZAdjustHover: -0.02 - m_ZAdjustClick: 0.05 - m_HoverScale: 1.1 - m_HoverBoxColliderGrow: 0.2 - m_AddOverlay: 0 - m_Command: 0 - m_CommandParam: -1 - m_CommandParam2: -1 - m_RequiresPopup: 0 - m_CenterPopupOnButton: 0 - m_PopupOffset: {x: 0, y: 0, z: 0} - m_PopupText: - m_LocalizedPopup: - m_TableReference: - m_TableCollectionName: - m_TableEntryReference: - m_KeyId: 0 - m_Key: - m_FallbackState: 0 - m_WaitForCompletion: 0 - m_LocalVariables: [] - m_ToggleOnDescription: - m_LocalizedToggleOnDescription: - m_TableReference: - m_TableCollectionName: - m_TableEntryReference: - m_KeyId: 0 - m_Key: - m_FallbackState: 0 - m_WaitForCompletion: 0 - m_LocalVariables: [] - m_ToggleOnTexture: {fileID: 0} - m_AllowUnavailable: 0 - m_LinkedUIObject: {fileID: 0} - m_CommandIgnored: 0 - references: - version: 2 - RefIds: [] ---- !u!1 &1420984185611099820 -GameObject: +--- !u!1 &346980884099360615 +GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 6124434747938532598} - - component: {fileID: 3587958868994276479} - - component: {fileID: 8764641029886384522} - - component: {fileID: 320158017192318128} - - component: {fileID: 6728525253942131070} - m_Layer: 16 - m_Name: Sketchfab_SignOut + - component: {fileID: 7219417712597752172} + - component: {fileID: 6131316858001926440} + - component: {fileID: 2193359757602459023} + - component: {fileID: 4899035600685365074} + m_Layer: 0 + m_Name: Description m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!4 &6124434747938532598 -Transform: +--- !u!224 &7219417712597752172 +RectTransform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1420984185611099820} + m_GameObject: {fileID: 346980884099360615} m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0.845, y: -0.242, z: -0.06} - m_LocalScale: {x: 0.35, y: 0.35, z: 0.35} + m_LocalPosition: {x: 0, y: 0, z: -0.0025} + m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] - m_Father: {fileID: 6423827612944397798} - m_RootOrder: 2 + m_Father: {fileID: 6373137851377895237} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!33 &3587958868994276479 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1420984185611099820} - m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} ---- !u!23 &8764641029886384522 + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0.058} + m_SizeDelta: {x: 2.5, y: 0.7} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!23 &6131316858001926440 MeshRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1420984185611099820} + m_GameObject: {fileID: 346980884099360615} m_Enabled: 1 m_CastShadows: 0 m_ReceiveShadows: 0 m_DynamicOccludee: 1 m_StaticShadowCaster: 0 m_MotionVectors: 1 - m_LightProbeUsage: 1 + m_LightProbeUsage: 0 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 2100000, guid: 3c8ca511828182747a0b79564892ec57, type: 2} + - {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 @@ -775,7 +736,7 @@ MeshRenderer: m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 m_ReceiveGI: 1 - m_PreserveUVs: 1 + m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 m_StitchLightmapSeams: 0 @@ -788,161 +749,204 @@ MeshRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!114 &320158017192318128 +--- !u!114 &2193359757602459023 MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1420984185611099820} + m_GameObject: {fileID: 346980884099360615} m_Enabled: 1 m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 6c6859eec74651247968d56b594ac313, type: 3} + m_Script: {fileID: 11500000, guid: 9541d86e2fd84c1d9990edf0852d74ab, type: 3} m_Name: m_EditorClassIdentifier: - m_DescriptionType: 0 - m_DescriptionYOffset: 0 - m_DescriptionText: Sign Out - m_LocalizedDescription: - m_TableReference: - m_TableCollectionName: GUID:c84355079ab3f3e4f8f3812258805f86 - m_TableEntryReference: - m_KeyId: 15522362785837056 - m_Key: - m_FallbackState: 0 - m_WaitForCompletion: 0 - m_LocalVariables: [] - m_DescriptionTextExtra: - m_LocalizedDescriptionExtra: - m_TableReference: - m_TableCollectionName: - m_TableEntryReference: - m_KeyId: 0 - m_Key: - m_FallbackState: 0 - m_WaitForCompletion: 0 - m_LocalVariables: [] - m_DescriptionActivateSpeed: 12 - m_DescriptionZScale: 1 - m_ButtonTexture: {fileID: 2800000, guid: 6bd8742b210a6444e85b5c86f80ffebc, type: 3} - m_AtlasTexture: 1 - m_ToggleButton: 0 - m_LongPressReleaseButton: 0 - m_ButtonHasPressedAudio: 1 - m_ZAdjustHover: -0.02 - m_ZAdjustClick: 0.05 - m_HoverScale: 1.1 - m_HoverBoxColliderGrow: 0.2 - m_AddOverlay: 0 - m_Command: 27 - m_CommandParam: 2 - m_CommandParam2: -1 - m_RequiresPopup: 0 - m_CenterPopupOnButton: 0 - m_PopupOffset: {x: 0, y: 0, z: 0} - m_PopupText: - m_LocalizedPopup: - m_TableReference: - m_TableCollectionName: - m_TableEntryReference: - m_KeyId: 0 - m_Key: - m_FallbackState: 0 - m_WaitForCompletion: 0 - m_LocalVariables: [] - m_ToggleOnDescription: - m_LocalizedToggleOnDescription: - m_TableReference: - m_TableCollectionName: - m_TableEntryReference: - m_KeyId: 0 - m_Key: - m_FallbackState: 0 - m_WaitForCompletion: 0 - m_LocalVariables: [] - m_ToggleOnTexture: {fileID: 0} - m_AllowUnavailable: 0 - m_LinkedUIObject: {fileID: 0} - references: - version: 2 - RefIds: [] ---- !u!65 &6728525253942131070 -BoxCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1420984185611099820} m_Material: {fileID: 0} - m_IsTrigger: 0 - m_Enabled: 1 - serializedVersion: 2 - m_Size: {x: 1, y: 1.0000001, z: 0.1} - m_Center: {x: 0, y: 0, z: -0.01} ---- !u!1 &2114749234407238233 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 7314565180282189882} - - component: {fileID: 3237075444271635601} - - component: {fileID: 5760690751225334939} - - component: {fileID: 1021251213275692761} - - component: {fileID: 5408017822027362464} - m_Layer: 16 - m_Name: Sketchfab_SignOut - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &7314565180282189882 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2114749234407238233} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 1.041, y: 0.247, z: -0.02499998} - m_LocalScale: {x: 0.25, y: 0.24999991, z: 0.2499999} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 529827201699571093} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!33 &3237075444271635601 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2114749234407238233} - m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} ---- !u!23 &5760690751225334939 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2114749234407238233} - m_Enabled: 1 - m_CastShadows: 0 - m_ReceiveShadows: 0 - m_DynamicOccludee: 1 - m_StaticShadowCaster: 0 - m_MotionVectors: 1 - m_LightProbeUsage: 0 + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_text: 'Sign in to an Icosa account to allow + + uploading to Icosa.' + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} + m_sharedMaterial: {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4286085240 + m_fontColor: {r: 0.47058824, g: 0.47058824, b: 0.47058824, a: 1} + m_enableVertexGradient: 0 + m_colorMode: 3 + m_fontColorGradient: + topLeft: {r: 1, g: 1, b: 1, a: 1} + topRight: {r: 1, g: 1, b: 1, a: 1} + bottomLeft: {r: 1, g: 1, b: 1, a: 1} + bottomRight: {r: 1, g: 1, b: 1, a: 1} + m_fontColorGradientPreset: {fileID: 0} + m_spriteAsset: {fileID: 0} + m_tintAllSprites: 0 + m_StyleSheet: {fileID: 0} + m_TextStyleHashCode: -1183493901 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_fontSize: 1.275 + m_fontSizeBase: 1.275 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_HorizontalAlignment: 2 + m_VerticalAlignment: 512 + m_textAlignment: 65535 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_enableWordWrapping: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 0 + m_isCullingEnabled: 0 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_IsTextObjectScaleStatic: 0 + m_VertexBufferAutoSizeReduction: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + _SortingLayer: 0 + _SortingLayerID: 0 + _SortingOrder: 0 + m_hasFontAssetChanged: 0 + m_renderer: {fileID: 6131316858001926440} + m_maskType: 0 +--- !u!114 &4899035600685365074 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 346980884099360615} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 69beb381e244f92449b8c4cf954630e9, type: 3} + m_Name: + m_EditorClassIdentifier: + m_TrackedObjects: + - rid: 3215294302546034856 + references: + version: 2 + RefIds: + - rid: 3215294302546034856 + type: {class: TrackedUGuiGraphic, ns: UnityEngine.Localization.PropertyVariants.TrackedObjects, + asm: Unity.Localization} + data: + m_Target: {fileID: 2193359757602459023} + m_TrackedProperties: + items: + - rid: 3215294302546034857 + m_UpdateType: 0 + - rid: 3215294302546034857 + type: {class: LocalizedStringProperty, ns: UnityEngine.Localization.PropertyVariants.TrackedProperties, + asm: Unity.Localization} + data: + m_Localized: + m_TableReference: + m_TableCollectionName: GUID:c84355079ab3f3e4f8f3812258805f86 + m_TableEntryReference: + m_KeyId: 164911761917042688 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_PropertyPath: m_text +--- !u!1 &440723707841846920 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4590447671262214820} + - component: {fileID: 2121377069448007116} + - component: {fileID: 1795340145885663930} + - component: {fileID: 2756793802573776306} + - component: {fileID: 3740906181516385311} + m_Layer: 16 + m_Name: Google_Cancel + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4590447671262214820 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 440723707841846920} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: -0.845, y: -0.242, z: -0.06} + m_LocalScale: {x: 0.35, y: 0.35, z: 0.35} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 7741920746089690377} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!33 &2121377069448007116 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 440723707841846920} + m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &1795340145885663930 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 440723707841846920} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 2100000, guid: 3c8ca511828182747a0b79564892ec57, type: 2} + - {fileID: 2100000, guid: 40d29de2bdc11f04dbfa25059165916e, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 @@ -951,7 +955,7 @@ MeshRenderer: m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 m_ReceiveGI: 1 - m_PreserveUVs: 0 + m_PreserveUVs: 1 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 m_StitchLightmapSeams: 0 @@ -964,13 +968,13 @@ MeshRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!114 &1021251213275692761 +--- !u!114 &2756793802573776306 MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2114749234407238233} + m_GameObject: {fileID: 440723707841846920} m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: fc12adcafa62a22458e635d2ee7e78b5, type: 3} @@ -978,12 +982,12 @@ MonoBehaviour: m_EditorClassIdentifier: m_DescriptionType: 0 m_DescriptionYOffset: 0 - m_DescriptionText: POPUP_ACCOUNTS_SIGNOUT_BUTTON_DESCRIPTION + m_DescriptionText: POPUP_ACCOUNTS_CANCEL_BUTTON_DESCRIPTION m_LocalizedDescription: m_TableReference: m_TableCollectionName: GUID:c84355079ab3f3e4f8f3812258805f86 m_TableEntryReference: - m_KeyId: 15522362785837056 + m_KeyId: 15526523405381632 m_Key: m_FallbackState: 0 m_WaitForCompletion: 0 @@ -1000,8 +1004,8 @@ MonoBehaviour: m_LocalVariables: [] m_DescriptionActivateSpeed: 12 m_DescriptionZScale: 1 - m_ButtonTexture: {fileID: 2800000, guid: 42f600d7b08f5514ebdcf4604e0cfa6c, type: 3} - m_AtlasTexture: 1 + m_ButtonTexture: {fileID: 2800000, guid: 957f69e59565cd1469fa095b415fa513, type: 3} + m_AtlasTexture: 0 m_ToggleButton: 0 m_LongPressReleaseButton: 0 m_ButtonHasPressedAudio: 1 @@ -1010,8 +1014,8 @@ MonoBehaviour: m_HoverScale: 1.1 m_HoverBoxColliderGrow: 0.2 m_AddOverlay: 0 - m_Command: 98 - m_CommandParam: 2 + m_Command: 0 + m_CommandParam: 1 m_CommandParam2: -1 m_RequiresPopup: 0 m_CenterPopupOnButton: 0 @@ -1043,20 +1047,28 @@ MonoBehaviour: references: version: 2 RefIds: [] ---- !u!65 &5408017822027362464 +--- !u!65 &3740906181516385311 BoxCollider: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2114749234407238233} + m_GameObject: {fileID: 440723707841846920} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1, y: 1.0000001, z: 0.1} m_Center: {x: 0, y: 0, z: -0.01} ---- !u!1 &2130932365216558288 +--- !u!1 &710086474055226122 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -1064,58 +1076,64 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 7650010300803901743} - - component: {fileID: 4683226676648572474} - - component: {fileID: 6232891306609240420} - - component: {fileID: 4801091935649164795} - m_Layer: 0 - m_Name: Title + - component: {fileID: 7893921961113671483} + - component: {fileID: 8398224192364770992} + - component: {fileID: 5384180884118313375} + - component: {fileID: 1573872792934989801} + - component: {fileID: 1569796081246134525} + m_Layer: 16 + m_Name: Google_SignIn m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!224 &7650010300803901743 -RectTransform: +--- !u!4 &7893921961113671483 +Transform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2130932365216558288} + m_GameObject: {fileID: 710086474055226122} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: -0.0025} - m_LocalScale: {x: 1, y: 1, z: 1} + m_LocalPosition: {x: -0.634, y: -0.242, z: -0.06} + m_LocalScale: {x: 0.4, y: 0.4, z: 0.4} m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 3457603883277620212} - m_RootOrder: 0 + m_Children: + - {fileID: 1583684570998085433} + - {fileID: 5208561973859313428} + m_Father: {fileID: 1432546188030660464} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0.5, y: 0.5} - m_AnchorMax: {x: 0.5, y: 0.5} - m_AnchoredPosition: {x: 0, y: 0.5} - m_SizeDelta: {x: 2.27, y: 0.3} - m_Pivot: {x: 0.5, y: 0.5} ---- !u!23 &4683226676648572474 +--- !u!33 &8398224192364770992 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 710086474055226122} + m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &5384180884118313375 MeshRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2130932365216558288} - m_Enabled: 1 + m_GameObject: {fileID: 710086474055226122} + m_Enabled: 0 m_CastShadows: 0 m_ReceiveShadows: 0 m_DynamicOccludee: 1 m_StaticShadowCaster: 0 m_MotionVectors: 1 - m_LightProbeUsage: 0 + m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} + - {fileID: 2100000, guid: 005edae3a0d4d1243ba88ed7543cd61d, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 @@ -1124,7 +1142,7 @@ MeshRenderer: m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 m_ReceiveGI: 1 - m_PreserveUVs: 0 + m_PreserveUVs: 1 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 m_StitchLightmapSeams: 0 @@ -1137,139 +1155,107 @@ MeshRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!114 &6232891306609240420 +--- !u!114 &1573872792934989801 MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2130932365216558288} + m_GameObject: {fileID: 710086474055226122} m_Enabled: 1 m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 9541d86e2fd84c1d9990edf0852d74ab, type: 3} + m_Script: {fileID: 11500000, guid: fc12adcafa62a22458e635d2ee7e78b5, type: 3} m_Name: m_EditorClassIdentifier: - m_Material: {fileID: 0} - m_Color: {r: 1, g: 1, b: 1, a: 1} - m_RaycastTarget: 1 - m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} - m_Maskable: 1 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_text: Share to Sketchfab - m_isRightToLeft: 0 - m_fontAsset: {fileID: 11400000, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} - m_sharedMaterial: {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} - m_fontSharedMaterials: [] - m_fontMaterial: {fileID: 0} - m_fontMaterials: [] - m_fontColor32: - serializedVersion: 2 - rgba: 4294967295 - m_fontColor: {r: 1, g: 1, b: 1, a: 1} - m_enableVertexGradient: 0 - m_colorMode: 3 - m_fontColorGradient: - topLeft: {r: 1, g: 1, b: 1, a: 1} - topRight: {r: 1, g: 1, b: 1, a: 1} - bottomLeft: {r: 1, g: 1, b: 1, a: 1} - bottomRight: {r: 1, g: 1, b: 1, a: 1} - m_fontColorGradientPreset: {fileID: 0} - m_spriteAsset: {fileID: 0} - m_tintAllSprites: 0 - m_StyleSheet: {fileID: 0} - m_TextStyleHashCode: -1183493901 - m_overrideHtmlColors: 0 - m_faceColor: - serializedVersion: 2 - rgba: 4294967295 - m_fontSize: 1.915 - m_fontSizeBase: 1.915 - m_fontWeight: 400 - m_enableAutoSizing: 0 - m_fontSizeMin: 18 - m_fontSizeMax: 72 - m_fontStyle: 0 - m_HorizontalAlignment: 2 - m_VerticalAlignment: 512 - m_textAlignment: 65535 - m_characterSpacing: 0 - m_wordSpacing: 0 - m_lineSpacing: 0 - m_lineSpacingMax: 0 - m_paragraphSpacing: 0 - m_charWidthMaxAdj: 0 - m_enableWordWrapping: 1 - m_wordWrappingRatios: 0.4 - m_overflowMode: 0 - m_linkedTextComponent: {fileID: 0} - parentLinkedComponent: {fileID: 0} - m_enableKerning: 1 - m_enableExtraPadding: 0 - checkPaddingRequired: 0 - m_isRichText: 1 - m_parseCtrlCharacters: 1 - m_isOrthographic: 0 - m_isCullingEnabled: 0 - m_horizontalMapping: 0 - m_verticalMapping: 0 - m_uvLineOffset: 0 - m_geometrySortingOrder: 0 - m_IsTextObjectScaleStatic: 0 - m_VertexBufferAutoSizeReduction: 0 - m_useMaxVisibleDescender: 1 - m_pageToDisplay: 1 - m_margin: {x: 0, y: 0, z: 0, w: 0} - m_isUsingLegacyAnimationComponent: 0 - m_isVolumetricText: 0 - _SortingLayer: 0 - _SortingLayerID: 0 - _SortingOrder: 0 - m_hasFontAssetChanged: 0 - m_renderer: {fileID: 4683226676648572474} - m_maskType: 0 ---- !u!114 &4801091935649164795 -MonoBehaviour: + m_DescriptionType: -1 + m_DescriptionYOffset: 0 + m_DescriptionText: + m_LocalizedDescription: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_DescriptionTextExtra: + m_LocalizedDescriptionExtra: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_DescriptionActivateSpeed: 12 + m_DescriptionZScale: 1 + m_ButtonTexture: {fileID: 0} + m_AtlasTexture: 0 + m_ToggleButton: 0 + m_LongPressReleaseButton: 0 + m_ButtonHasPressedAudio: 1 + m_ZAdjustHover: -0.02 + m_ZAdjustClick: 0.05 + m_HoverScale: 1.1 + m_HoverBoxColliderGrow: 0.2 + m_AddOverlay: 0 + m_Command: 95 + m_CommandParam: 1 + m_CommandParam2: -1 + m_RequiresPopup: 0 + m_CenterPopupOnButton: 0 + m_PopupOffset: {x: 0, y: 0, z: 0} + m_PopupText: + m_LocalizedPopup: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_ToggleOnDescription: + m_LocalizedToggleOnDescription: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_ToggleOnTexture: {fileID: 0} + m_AllowUnavailable: 1 + m_LinkedUIObject: {fileID: 0} + m_CommandIgnored: 0 + references: + version: 2 + RefIds: [] +--- !u!65 &1569796081246134525 +BoxCollider: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2130932365216558288} + m_GameObject: {fileID: 710086474055226122} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 69beb381e244f92449b8c4cf954630e9, type: 3} - m_Name: - m_EditorClassIdentifier: - m_TrackedObjects: - - rid: 3215294302546034854 - references: - version: 2 - RefIds: - - rid: 3215294302546034854 - type: {class: TrackedUGuiGraphic, ns: UnityEngine.Localization.PropertyVariants.TrackedObjects, - asm: Unity.Localization} - data: - m_Target: {fileID: 6232891306609240420} - m_TrackedProperties: - items: - - rid: 3215294302546034855 - m_UpdateType: 0 - - rid: 3215294302546034855 - type: {class: LocalizedStringProperty, ns: UnityEngine.Localization.PropertyVariants.TrackedProperties, - asm: Unity.Localization} - data: - m_Localized: - m_TableReference: - m_TableCollectionName: GUID:c84355079ab3f3e4f8f3812258805f86 - m_TableEntryReference: - m_KeyId: 76138395621449728 - m_Key: - m_FallbackState: 0 - m_WaitForCompletion: 0 - m_LocalVariables: [] - m_PropertyPath: m_text ---- !u!1 &2181120061148835783 + serializedVersion: 3 + m_Size: {x: 2, y: 1.0000001, z: 0.1} + m_Center: {x: 0, y: 0, z: -0.01} +--- !u!1 &805844845446197852 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -1277,79 +1263,51 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 3457603883277620212} - m_Layer: 16 - m_Name: SketchfabInfoElements + - component: {fileID: 7338107887349877872} + - component: {fileID: 6941474665913055402} + - component: {fileID: 796423230181286760} + - component: {fileID: 422651024943017319} + - component: {fileID: 5581805715966274588} + m_Layer: 14 + m_Name: ConfirmationButton m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 - m_IsActive: 0 ---- !u!4 &3457603883277620212 + m_IsActive: 1 +--- !u!4 &7338107887349877872 Transform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2181120061148835783} + m_GameObject: {fileID: 805844845446197852} + serializedVersion: 2 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_LocalPosition: {x: 0, y: -0.434, z: -0.08} + m_LocalScale: {x: 0.6, y: 0.29999998, z: 0.29999998} m_ConstrainProportionsScale: 0 m_Children: - - {fileID: 7650010300803901743} - - {fileID: 4704522903857296483} - - {fileID: 7338107887349877872} - m_Father: {fileID: 8645625734765961102} - m_RootOrder: 4 + - {fileID: 6454029799957143386} + - {fileID: 8006143071345660080} + m_Father: {fileID: 3457603883277620212} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &2524197670113838527 -GameObject: +--- !u!33 &6941474665913055402 +MeshFilter: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1829480651769887961} - - component: {fileID: 3001700515688151744} - - component: {fileID: 1883450177596816156} - - component: {fileID: 5438294757481915153} - m_Layer: 16 - m_Name: Got it - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!224 &1829480651769887961 -RectTransform: + m_GameObject: {fileID: 805844845446197852} + m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &796423230181286760 +MeshRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2524197670113838527} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: -0.029333334} - m_LocalScale: {x: 2.9528668, y: 5.9057336, z: 2.9528668} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 8645625735159627316} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0.5, y: 0.5} - m_AnchorMax: {x: 0.5, y: 0.5} - m_AnchoredPosition: {x: 0.141, y: 0} - m_SizeDelta: {x: 0.25, y: 0.15} - m_Pivot: {x: 0.5, y: 0.5} ---- !u!23 &3001700515688151744 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2524197670113838527} - m_Enabled: 1 + m_GameObject: {fileID: 805844845446197852} + m_Enabled: 0 m_CastShadows: 0 m_ReceiveShadows: 0 m_DynamicOccludee: 1 @@ -1362,7 +1320,7 @@ MeshRenderer: m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} + - {fileID: 2100000, guid: 3c8ca511828182747a0b79564892ec57, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 @@ -1384,139 +1342,107 @@ MeshRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!114 &1883450177596816156 -MonoBehaviour: +--- !u!65 &422651024943017319 +BoxCollider: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2524197670113838527} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 9541d86e2fd84c1d9990edf0852d74ab, type: 3} - m_Name: - m_EditorClassIdentifier: + m_GameObject: {fileID: 805844845446197852} m_Material: {fileID: 0} - m_Color: {r: 1, g: 1, b: 1, a: 1} - m_RaycastTarget: 1 - m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} - m_Maskable: 1 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_text: GOT IT - m_isRightToLeft: 0 - m_fontAsset: {fileID: 11400000, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} - m_sharedMaterial: {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} - m_fontSharedMaterials: [] - m_fontMaterial: {fileID: 0} - m_fontMaterials: [] - m_fontColor32: + m_IncludeLayers: serializedVersion: 2 - rgba: 4294967295 - m_fontColor: {r: 1, g: 1, b: 1, a: 1} - m_enableVertexGradient: 0 - m_colorMode: 3 - m_fontColorGradient: - topLeft: {r: 1, g: 1, b: 1, a: 1} - topRight: {r: 1, g: 1, b: 1, a: 1} - bottomLeft: {r: 1, g: 1, b: 1, a: 1} - bottomRight: {r: 1, g: 1, b: 1, a: 1} - m_fontColorGradientPreset: {fileID: 0} - m_spriteAsset: {fileID: 0} - m_tintAllSprites: 0 - m_StyleSheet: {fileID: 0} - m_TextStyleHashCode: -1183493901 - m_overrideHtmlColors: 0 - m_faceColor: + m_Bits: 0 + m_ExcludeLayers: serializedVersion: 2 - rgba: 4294967295 - m_fontSize: 0.64 - m_fontSizeBase: 0.64 - m_fontWeight: 400 - m_enableAutoSizing: 0 - m_fontSizeMin: 18 - m_fontSizeMax: 72 - m_fontStyle: 0 - m_HorizontalAlignment: 2 - m_VerticalAlignment: 512 - m_textAlignment: 65535 - m_characterSpacing: 0 - m_wordSpacing: 0 - m_lineSpacing: 0 - m_lineSpacingMax: 0 - m_paragraphSpacing: 0 - m_charWidthMaxAdj: 0 - m_enableWordWrapping: 1 - m_wordWrappingRatios: 0.4 - m_overflowMode: 0 - m_linkedTextComponent: {fileID: 0} - parentLinkedComponent: {fileID: 0} - m_enableKerning: 1 - m_enableExtraPadding: 0 - checkPaddingRequired: 0 - m_isRichText: 1 - m_parseCtrlCharacters: 1 - m_isOrthographic: 0 - m_isCullingEnabled: 0 - m_horizontalMapping: 0 - m_verticalMapping: 0 - m_uvLineOffset: 0 - m_geometrySortingOrder: 0 - m_IsTextObjectScaleStatic: 0 - m_VertexBufferAutoSizeReduction: 0 - m_useMaxVisibleDescender: 1 - m_pageToDisplay: 1 - m_margin: {x: 0, y: 0, z: 0, w: 0} - m_isUsingLegacyAnimationComponent: 0 - m_isVolumetricText: 0 - _SortingLayer: 0 - _SortingLayerID: 0 - _SortingOrder: 0 - m_hasFontAssetChanged: 0 - m_renderer: {fileID: 3001700515688151744} - m_maskType: 0 ---- !u!114 &5438294757481915153 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Size: {x: 1, y: 1, z: 0.01} + m_Center: {x: 0, y: 0, z: -0.01} +--- !u!114 &5581805715966274588 MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2524197670113838527} + m_GameObject: {fileID: 805844845446197852} m_Enabled: 1 m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 69beb381e244f92449b8c4cf954630e9, type: 3} + m_Script: {fileID: 11500000, guid: fc12adcafa62a22458e635d2ee7e78b5, type: 3} m_Name: m_EditorClassIdentifier: - m_TrackedObjects: - - rid: 3215294302546034844 + m_DescriptionType: -1 + m_DescriptionYOffset: 0 + m_DescriptionText: + m_LocalizedDescription: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_DescriptionTextExtra: + m_LocalizedDescriptionExtra: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_DescriptionActivateSpeed: 12 + m_DescriptionZScale: 1 + m_ButtonTexture: {fileID: 0} + m_AtlasTexture: 0 + m_ToggleButton: 0 + m_LongPressReleaseButton: 0 + m_ButtonHasPressedAudio: 1 + m_ZAdjustHover: -0.02 + m_ZAdjustClick: 0.05 + m_HoverScale: 1.1 + m_HoverBoxColliderGrow: 0.2 + m_AddOverlay: 0 + m_Command: 0 + m_CommandParam: -1 + m_CommandParam2: -1 + m_RequiresPopup: 0 + m_CenterPopupOnButton: 0 + m_PopupOffset: {x: 0, y: 0, z: 0} + m_PopupText: + m_LocalizedPopup: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_ToggleOnDescription: + m_LocalizedToggleOnDescription: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_ToggleOnTexture: {fileID: 0} + m_AllowUnavailable: 0 + m_LinkedUIObject: {fileID: 0} + m_CommandIgnored: 0 references: version: 2 - RefIds: - - rid: 3215294302546034844 - type: {class: TrackedUGuiGraphic, ns: UnityEngine.Localization.PropertyVariants.TrackedObjects, - asm: Unity.Localization} - data: - m_Target: {fileID: 1883450177596816156} - m_TrackedProperties: - items: - - rid: 3215294302546034845 - m_UpdateType: 0 - - rid: 3215294302546034845 - type: {class: LocalizedStringProperty, ns: UnityEngine.Localization.PropertyVariants.TrackedProperties, - asm: Unity.Localization} - data: - m_Localized: - m_TableReference: - m_TableCollectionName: GUID:c84355079ab3f3e4f8f3812258805f86 - m_TableEntryReference: - m_KeyId: 76036746777255936 - m_Key: - m_FallbackState: 0 - m_WaitForCompletion: 0 - m_LocalVariables: [] - m_PropertyPath: m_text ---- !u!1 &2539912369590534119 + RefIds: [] +--- !u!1 &1206425102053680919 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -1524,46 +1450,46 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 8671432921432109627} - - component: {fileID: 2328370020170245272} - - component: {fileID: 3823398956549937895} + - component: {fileID: 2257200555475620437} + - component: {fileID: 5694728525219628291} + - component: {fileID: 8082422626311802404} m_Layer: 16 - m_Name: Google_BackPlate + m_Name: Background m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!4 &8671432921432109627 +--- !u!4 &2257200555475620437 Transform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2539912369590534119} - m_LocalRotation: {x: -0.7071068, y: -0, z: -0, w: 0.7071067} - m_LocalPosition: {x: -0.7238, y: 0.2550001, z: -0.005} - m_LocalScale: {x: 32, y: 32, z: 20} + m_GameObject: {fileID: 1206425102053680919} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0.0021666286, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] - m_Father: {fileID: 1432546188030660464} - m_RootOrder: 0 + m_Father: {fileID: 7500850895307564819} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!33 &2328370020170245272 +--- !u!33 &5694728525219628291 MeshFilter: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2539912369590534119} - m_Mesh: {fileID: 4300002, guid: 3efe5b86b55995545a231ce66a53b402, type: 3} ---- !u!23 &3823398956549937895 + m_GameObject: {fileID: 1206425102053680919} + m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &8082422626311802404 MeshRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2539912369590534119} + m_GameObject: {fileID: 1206425102053680919} m_Enabled: 1 m_CastShadows: 0 m_ReceiveShadows: 0 @@ -1577,7 +1503,7 @@ MeshRenderer: m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 2100000, guid: 8fe8230ee7ae32a4eb7fe6d5df34ebd4, type: 2} + - {fileID: 2100000, guid: 39d7053101c6e8e4b8d692eddc65d2b2, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 @@ -1586,7 +1512,7 @@ MeshRenderer: m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 m_ReceiveGI: 1 - m_PreserveUVs: 0 + m_PreserveUVs: 1 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 m_StitchLightmapSeams: 0 @@ -1599,7 +1525,7 @@ MeshRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!1 &2541333487600552761 +--- !u!1 &1420984185611099820 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -1607,46 +1533,48 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 4100876239645834569} - - component: {fileID: 7900905264382626932} - - component: {fileID: 6231791383006965005} + - component: {fileID: 6124434747938532598} + - component: {fileID: 3587958868994276479} + - component: {fileID: 8764641029886384522} + - component: {fileID: 320158017192318128} + - component: {fileID: 6728525253942131070} m_Layer: 16 - m_Name: MeshBackground + m_Name: Sketchfab_SignOut m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!4 &4100876239645834569 +--- !u!4 &6124434747938532598 Transform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2541333487600552761} - m_LocalRotation: {x: 0.7071068, y: -0, z: -0, w: 0.7071068} - m_LocalPosition: {x: 0, y: 0, z: 0.025} - m_LocalScale: {x: 0.79999995, y: 0.02, z: 0.8} + m_GameObject: {fileID: 1420984185611099820} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0.845, y: -0.242, z: -0.06} + m_LocalScale: {x: 0.35, y: 0.35, z: 0.35} m_ConstrainProportionsScale: 0 m_Children: [] - m_Father: {fileID: 5521146392998997215} - m_RootOrder: 1 - m_LocalEulerAnglesHint: {x: 90, y: 0, z: 0} ---- !u!33 &7900905264382626932 + m_Father: {fileID: 6423827612944397798} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!33 &3587958868994276479 MeshFilter: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2541333487600552761} - m_Mesh: {fileID: 10206, guid: 0000000000000000e000000000000000, type: 0} ---- !u!23 &6231791383006965005 + m_GameObject: {fileID: 1420984185611099820} + m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &8764641029886384522 MeshRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2541333487600552761} + m_GameObject: {fileID: 1420984185611099820} m_Enabled: 1 m_CastShadows: 0 m_ReceiveShadows: 0 @@ -1660,7 +1588,7 @@ MeshRenderer: m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 2100000, guid: 77dd4ff8b1158a84397aba783cd0af05, type: 2} + - {fileID: 2100000, guid: 3c8ca511828182747a0b79564892ec57, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 @@ -1682,7 +1610,106 @@ MeshRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!1 &2615357070484673490 +--- !u!114 &320158017192318128 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1420984185611099820} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 6c6859eec74651247968d56b594ac313, type: 3} + m_Name: + m_EditorClassIdentifier: + m_DescriptionType: 0 + m_DescriptionYOffset: 0 + m_DescriptionText: Sign Out + m_LocalizedDescription: + m_TableReference: + m_TableCollectionName: GUID:c84355079ab3f3e4f8f3812258805f86 + m_TableEntryReference: + m_KeyId: 15522362785837056 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_DescriptionTextExtra: + m_LocalizedDescriptionExtra: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_DescriptionActivateSpeed: 12 + m_DescriptionZScale: 1 + m_ButtonTexture: {fileID: 2800000, guid: 6bd8742b210a6444e85b5c86f80ffebc, type: 3} + m_AtlasTexture: 1 + m_ToggleButton: 0 + m_LongPressReleaseButton: 0 + m_ButtonHasPressedAudio: 1 + m_ZAdjustHover: -0.02 + m_ZAdjustClick: 0.05 + m_HoverScale: 1.1 + m_HoverBoxColliderGrow: 0.2 + m_AddOverlay: 0 + m_Command: 27 + m_CommandParam: 2 + m_CommandParam2: -1 + m_RequiresPopup: 0 + m_CenterPopupOnButton: 0 + m_PopupOffset: {x: 0, y: 0, z: 0} + m_PopupText: + m_LocalizedPopup: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_ToggleOnDescription: + m_LocalizedToggleOnDescription: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_ToggleOnTexture: {fileID: 0} + m_AllowUnavailable: 0 + m_LinkedUIObject: {fileID: 0} + references: + version: 2 + RefIds: [] +--- !u!65 &6728525253942131070 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1420984185611099820} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Size: {x: 1, y: 1.0000001, z: 0.1} + m_Center: {x: 0, y: 0, z: -0.01} +--- !u!1 &1595746536817818034 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -1690,46 +1717,48 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 8245513620673000221} - - component: {fileID: 8539932158365628172} - - component: {fileID: 3222010795993119791} + - component: {fileID: 9030048754727846959} + - component: {fileID: 8449302079573380106} + - component: {fileID: 7547523069343855482} + - component: {fileID: 4678841376964907514} + - component: {fileID: 4846547509098454009} m_Layer: 16 - m_Name: Sketchfab_BackPlate + m_Name: Icosa_SignOut m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!4 &8245513620673000221 +--- !u!4 &9030048754727846959 Transform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2615357070484673490} - m_LocalRotation: {x: -0.7071068, y: -0, z: -0, w: 0.7071067} - m_LocalPosition: {x: 0.622, y: 0.2550001, z: -0.005} - m_LocalScale: {x: 32, y: 32, z: 20} + m_GameObject: {fileID: 1595746536817818034} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0.845, y: -0.242, z: -0.06} + m_LocalScale: {x: 0.35, y: 0.35, z: 0.35} m_ConstrainProportionsScale: 0 m_Children: [] - m_Father: {fileID: 6423827612944397798} - m_RootOrder: 0 + m_Father: {fileID: 1675920430848132177} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!33 &8539932158365628172 +--- !u!33 &8449302079573380106 MeshFilter: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2615357070484673490} - m_Mesh: {fileID: 4300002, guid: 3efe5b86b55995545a231ce66a53b402, type: 3} ---- !u!23 &3222010795993119791 + m_GameObject: {fileID: 1595746536817818034} + m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &7547523069343855482 MeshRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2615357070484673490} + m_GameObject: {fileID: 1595746536817818034} m_Enabled: 1 m_CastShadows: 0 m_ReceiveShadows: 0 @@ -1743,7 +1772,7 @@ MeshRenderer: m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 2100000, guid: 8fe8230ee7ae32a4eb7fe6d5df34ebd4, type: 2} + - {fileID: 2100000, guid: 3c8ca511828182747a0b79564892ec57, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 @@ -1752,7 +1781,7 @@ MeshRenderer: m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 m_ReceiveGI: 1 - m_PreserveUVs: 0 + m_PreserveUVs: 1 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 m_StitchLightmapSeams: 0 @@ -1765,7 +1794,106 @@ MeshRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!1 &2675879709888175167 +--- !u!114 &4678841376964907514 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1595746536817818034} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 6c6859eec74651247968d56b594ac313, type: 3} + m_Name: + m_EditorClassIdentifier: + m_DescriptionType: 0 + m_DescriptionYOffset: 0 + m_DescriptionText: Sign Out + m_LocalizedDescription: + m_TableReference: + m_TableCollectionName: GUID:c84355079ab3f3e4f8f3812258805f86 + m_TableEntryReference: + m_KeyId: 15522362785837056 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_DescriptionTextExtra: + m_LocalizedDescriptionExtra: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_DescriptionActivateSpeed: 12 + m_DescriptionZScale: 1 + m_ButtonTexture: {fileID: 2800000, guid: 6bd8742b210a6444e85b5c86f80ffebc, type: 3} + m_AtlasTexture: 1 + m_ToggleButton: 0 + m_LongPressReleaseButton: 0 + m_ButtonHasPressedAudio: 1 + m_ZAdjustHover: -0.02 + m_ZAdjustClick: 0.05 + m_HoverScale: 1.1 + m_HoverBoxColliderGrow: 0.2 + m_AddOverlay: 0 + m_Command: 27 + m_CommandParam: 3 + m_CommandParam2: -1 + m_RequiresPopup: 0 + m_CenterPopupOnButton: 0 + m_PopupOffset: {x: 0, y: 0, z: 0} + m_PopupText: + m_LocalizedPopup: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_ToggleOnDescription: + m_LocalizedToggleOnDescription: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_ToggleOnTexture: {fileID: 0} + m_AllowUnavailable: 0 + m_LinkedUIObject: {fileID: 0} + references: + version: 2 + RefIds: [] +--- !u!65 &4846547509098454009 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1595746536817818034} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Size: {x: 1, y: 1.0000001, z: 0.1} + m_Center: {x: 0, y: 0, z: -0.01} +--- !u!1 &1666263515128110337 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -1773,43 +1901,46 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 90735575297890764} - - component: {fileID: 6241670906414567126} - - component: {fileID: 3509174102411407934} - m_Layer: 0 - m_Name: Sketchfab_Name + - component: {fileID: 3326273886487770573} + - component: {fileID: 2034091918340690625} + - component: {fileID: 9015730477659628009} + m_Layer: 16 + m_Name: Icosa_BackPlate m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!224 &90735575297890764 -RectTransform: +--- !u!4 &3326273886487770573 +Transform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2675879709888175167} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: -0.010000003} - m_LocalScale: {x: 1, y: 1, z: 1} + m_GameObject: {fileID: 1666263515128110337} + serializedVersion: 2 + m_LocalRotation: {x: -0.7071068, y: -0, z: -0, w: 0.7071067} + m_LocalPosition: {x: 0.53499997, y: 0.2550001, z: -0.005} + m_LocalScale: {x: 32, y: 32, z: 20} m_ConstrainProportionsScale: 0 m_Children: [] - m_Father: {fileID: 529827201699571093} - m_RootOrder: 2 + m_Father: {fileID: 1000721931266647293} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 0} - m_AnchorMax: {x: 0, y: 0} - m_AnchoredPosition: {x: 0.059, y: -0.477} - m_SizeDelta: {x: 1.1, y: 0.35} - m_Pivot: {x: 0, y: 0} ---- !u!23 &6241670906414567126 +--- !u!33 &2034091918340690625 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1666263515128110337} + m_Mesh: {fileID: 4300002, guid: 3efe5b86b55995545a231ce66a53b402, type: 3} +--- !u!23 &9015730477659628009 MeshRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2675879709888175167} + m_GameObject: {fileID: 1666263515128110337} m_Enabled: 1 m_CastShadows: 0 m_ReceiveShadows: 0 @@ -1823,7 +1954,7 @@ MeshRenderer: m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} + - {fileID: 2100000, guid: 8fe8230ee7ae32a4eb7fe6d5df34ebd4, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 @@ -1845,99 +1976,7 @@ MeshRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!114 &3509174102411407934 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2675879709888175167} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 9541d86e2fd84c1d9990edf0852d74ab, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Material: {fileID: 0} - m_Color: {r: 1, g: 1, b: 1, a: 1} - m_RaycastTarget: 1 - m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} - m_Maskable: 1 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_text: Longnamefirstname Longnamesurname - m_isRightToLeft: 0 - m_fontAsset: {fileID: 11400000, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} - m_sharedMaterial: {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} - m_fontSharedMaterials: [] - m_fontMaterial: {fileID: 0} - m_fontMaterials: [] - m_fontColor32: - serializedVersion: 2 - rgba: 4294967295 - m_fontColor: {r: 1, g: 1, b: 1, a: 1} - m_enableVertexGradient: 0 - m_colorMode: 3 - m_fontColorGradient: - topLeft: {r: 1, g: 1, b: 1, a: 1} - topRight: {r: 1, g: 1, b: 1, a: 1} - bottomLeft: {r: 1, g: 1, b: 1, a: 1} - bottomRight: {r: 1, g: 1, b: 1, a: 1} - m_fontColorGradientPreset: {fileID: 0} - m_spriteAsset: {fileID: 0} - m_tintAllSprites: 0 - m_StyleSheet: {fileID: 0} - m_TextStyleHashCode: -1183493901 - m_overrideHtmlColors: 0 - m_faceColor: - serializedVersion: 2 - rgba: 4294967295 - m_fontSize: 1.3 - m_fontSizeBase: 1.3 - m_fontWeight: 400 - m_enableAutoSizing: 0 - m_fontSizeMin: 18 - m_fontSizeMax: 72 - m_fontStyle: 0 - m_HorizontalAlignment: 2 - m_VerticalAlignment: 256 - m_textAlignment: 65535 - m_characterSpacing: 0 - m_wordSpacing: 0 - m_lineSpacing: -22 - m_lineSpacingMax: 0 - m_paragraphSpacing: 0 - m_charWidthMaxAdj: 0 - m_enableWordWrapping: 1 - m_wordWrappingRatios: 0.4 - m_overflowMode: 3 - m_linkedTextComponent: {fileID: 0} - parentLinkedComponent: {fileID: 0} - m_enableKerning: 1 - m_enableExtraPadding: 0 - checkPaddingRequired: 0 - m_isRichText: 1 - m_parseCtrlCharacters: 1 - m_isOrthographic: 0 - m_isCullingEnabled: 0 - m_horizontalMapping: 0 - m_verticalMapping: 0 - m_uvLineOffset: 0 - m_geometrySortingOrder: 0 - m_IsTextObjectScaleStatic: 0 - m_VertexBufferAutoSizeReduction: 1 - m_useMaxVisibleDescender: 1 - m_pageToDisplay: 1 - m_margin: {x: 0, y: 0, z: 0, w: 0} - m_isUsingLegacyAnimationComponent: 0 - m_isVolumetricText: 0 - _SortingLayer: 0 - _SortingLayerID: 0 - _SortingOrder: 0 - m_hasFontAssetChanged: 0 - m_renderer: {fileID: 6241670906414567126} - m_maskType: 0 ---- !u!1 &2727968127303647375 +--- !u!1 &2027372909421917180 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -1945,82 +1984,34 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 4153333614772809210} - - component: {fileID: 3359518694211327191} - - component: {fileID: 6165908306739578010} + - component: {fileID: 1675920430848132177} m_Layer: 16 - m_Name: IconDriveFull + m_Name: Icosa_ConfirmSignOutElements m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 - m_IsActive: 0 ---- !u!4 &4153333614772809210 + m_IsActive: 1 +--- !u!4 &1675920430848132177 Transform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2727968127303647375} + m_GameObject: {fileID: 2027372909421917180} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: -0.33714277, y: -0.011110305, z: -0.024999999} - m_LocalScale: {x: 0.21428569, y: 0.8333332, z: 0.15} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 1741904442304953456} - m_RootOrder: 2 + m_Children: + - {fileID: 8939772953772003517} + - {fileID: 7505721524787016835} + - {fileID: 9030048754727846959} + - {fileID: 1153672243062602464} + m_Father: {fileID: 7706333168622570552} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!33 &3359518694211327191 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2727968127303647375} - m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} ---- !u!23 &6165908306739578010 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2727968127303647375} - m_Enabled: 1 - m_CastShadows: 0 - m_ReceiveShadows: 0 - m_DynamicOccludee: 1 - m_StaticShadowCaster: 0 - m_MotionVectors: 1 - m_LightProbeUsage: 0 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RayTraceProcedural: 0 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 2100000, guid: 9cad1001e55b6a34083acc3b00f3a2aa, type: 2} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 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 - m_AdditionalVertexStreams: {fileID: 0} ---- !u!1 &2777064628006719104 +--- !u!1 &2114749234407238233 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -2028,64 +2019,62 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 181638217984195686} - - component: {fileID: 4757421857253066679} - - component: {fileID: 28647745892822175} - - component: {fileID: 8171971593979727739} - - component: {fileID: 811447535104194712} + - component: {fileID: 7314565180282189882} + - component: {fileID: 3237075444271635601} + - component: {fileID: 5760690751225334939} + - component: {fileID: 1021251213275692761} + - component: {fileID: 5408017822027362464} m_Layer: 16 - m_Name: Sketchfab_SignIn + m_Name: Sketchfab_SignOut m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!4 &181638217984195686 +--- !u!4 &7314565180282189882 Transform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2777064628006719104} + m_GameObject: {fileID: 2114749234407238233} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0.627, y: -0.242, z: -0.06} - m_LocalScale: {x: 0.4, y: 0.4, z: 0.4} + m_LocalPosition: {x: 1.041, y: 0.247, z: -0.02499998} + m_LocalScale: {x: 0.25, y: 0.24999991, z: 0.2499999} m_ConstrainProportionsScale: 0 - m_Children: - - {fileID: 3376029733079660750} - - {fileID: 7580573523043848490} - m_Father: {fileID: 534589999851858800} - m_RootOrder: 4 + m_Children: [] + m_Father: {fileID: 529827201699571093} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!33 &4757421857253066679 +--- !u!33 &3237075444271635601 MeshFilter: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2777064628006719104} + m_GameObject: {fileID: 2114749234407238233} m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} ---- !u!23 &28647745892822175 +--- !u!23 &5760690751225334939 MeshRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2777064628006719104} - m_Enabled: 0 + m_GameObject: {fileID: 2114749234407238233} + m_Enabled: 1 m_CastShadows: 0 m_ReceiveShadows: 0 m_DynamicOccludee: 1 m_StaticShadowCaster: 0 m_MotionVectors: 1 - m_LightProbeUsage: 1 + m_LightProbeUsage: 0 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 2100000, guid: 005edae3a0d4d1243ba88ed7543cd61d, type: 2} + - {fileID: 2100000, guid: 3c8ca511828182747a0b79564892ec57, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 @@ -2094,7 +2083,7 @@ MeshRenderer: m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 m_ReceiveGI: 1 - m_PreserveUVs: 1 + m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 m_StitchLightmapSeams: 0 @@ -2107,26 +2096,26 @@ MeshRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!114 &8171971593979727739 +--- !u!114 &1021251213275692761 MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2777064628006719104} + m_GameObject: {fileID: 2114749234407238233} m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: fc12adcafa62a22458e635d2ee7e78b5, type: 3} m_Name: m_EditorClassIdentifier: - m_DescriptionType: -1 + m_DescriptionType: 0 m_DescriptionYOffset: 0 - m_DescriptionText: + m_DescriptionText: POPUP_ACCOUNTS_SIGNOUT_BUTTON_DESCRIPTION m_LocalizedDescription: m_TableReference: - m_TableCollectionName: + m_TableCollectionName: GUID:c84355079ab3f3e4f8f3812258805f86 m_TableEntryReference: - m_KeyId: 0 + m_KeyId: 15522362785837056 m_Key: m_FallbackState: 0 m_WaitForCompletion: 0 @@ -2143,8 +2132,8 @@ MonoBehaviour: m_LocalVariables: [] m_DescriptionActivateSpeed: 12 m_DescriptionZScale: 1 - m_ButtonTexture: {fileID: 0} - m_AtlasTexture: 0 + m_ButtonTexture: {fileID: 2800000, guid: 42f600d7b08f5514ebdcf4604e0cfa6c, type: 3} + m_AtlasTexture: 1 m_ToggleButton: 0 m_LongPressReleaseButton: 0 m_ButtonHasPressedAudio: 1 @@ -2153,7 +2142,7 @@ MonoBehaviour: m_HoverScale: 1.1 m_HoverBoxColliderGrow: 0.2 m_AddOverlay: 0 - m_Command: 95 + m_Command: 98 m_CommandParam: 2 m_CommandParam2: -1 m_RequiresPopup: 0 @@ -2180,26 +2169,34 @@ MonoBehaviour: m_WaitForCompletion: 0 m_LocalVariables: [] m_ToggleOnTexture: {fileID: 0} - m_AllowUnavailable: 1 + m_AllowUnavailable: 0 m_LinkedUIObject: {fileID: 0} - m_CommandIgnored: 0 + m_CommandIgnored: 1 references: version: 2 RefIds: [] ---- !u!65 &811447535104194712 +--- !u!65 &5408017822027362464 BoxCollider: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2777064628006719104} + m_GameObject: {fileID: 2114749234407238233} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 - m_Size: {x: 2, y: 1.0000001, z: 0.1} + serializedVersion: 3 + m_Size: {x: 1, y: 1.0000001, z: 0.1} m_Center: {x: 0, y: 0, z: -0.01} ---- !u!1 &3204955315311320290 +--- !u!1 &2130932365216558288 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -2207,51 +2204,50 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 4111961635044152573} - - component: {fileID: 6060768737393671651} - - component: {fileID: 1725896781546607429} - - component: {fileID: 3626078249338065464} - m_Layer: 16 - m_Name: Sketchfab_Text + - component: {fileID: 7650010300803901743} + - component: {fileID: 4683226676648572474} + - component: {fileID: 6232891306609240420} + - component: {fileID: 4801091935649164795} + m_Layer: 0 + m_Name: Title m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!224 &4111961635044152573 +--- !u!224 &7650010300803901743 RectTransform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 3204955315311320290} + m_GameObject: {fileID: 2130932365216558288} m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: -0.01} + m_LocalPosition: {x: 0, y: 0, z: -0.0025} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] - m_Father: {fileID: 6423827612944397798} - m_RootOrder: 1 + m_Father: {fileID: 3457603883277620212} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} - m_AnchoredPosition: {x: 0.429, y: 0.3524501} - m_SizeDelta: {x: 0.52, y: 0.2} - m_Pivot: {x: 0, y: 1} ---- !u!23 &6060768737393671651 + m_AnchoredPosition: {x: 0, y: 0.5} + m_SizeDelta: {x: 2.27, y: 0.3} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!23 &4683226676648572474 MeshRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 3204955315311320290} + m_GameObject: {fileID: 2130932365216558288} m_Enabled: 1 m_CastShadows: 0 m_ReceiveShadows: 0 m_DynamicOccludee: 1 m_StaticShadowCaster: 0 m_MotionVectors: 1 - m_LightProbeUsage: 1 + m_LightProbeUsage: 0 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 m_RayTraceProcedural: 0 @@ -2270,7 +2266,7 @@ MeshRenderer: m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 - m_StitchLightmapSeams: 1 + m_StitchLightmapSeams: 0 m_SelectedEditorRenderState: 3 m_MinimumChartSize: 4 m_AutoUVMaxDistance: 0.5 @@ -2280,13 +2276,13 @@ MeshRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!114 &1725896781546607429 +--- !u!114 &6232891306609240420 MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 3204955315311320290} + m_GameObject: {fileID: 2130932365216558288} m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 9541d86e2fd84c1d9990edf0852d74ab, type: 3} @@ -2300,7 +2296,7 @@ MonoBehaviour: m_OnCullStateChanged: m_PersistentCalls: m_Calls: [] - m_text: Sign Out? + m_text: Share to Sketchfab m_isRightToLeft: 0 m_fontAsset: {fileID: 11400000, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} m_sharedMaterial: {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} @@ -2327,15 +2323,15 @@ MonoBehaviour: m_faceColor: serializedVersion: 2 rgba: 4294967295 - m_fontSize: 1.35 - m_fontSizeBase: 1.35 + m_fontSize: 1.915 + m_fontSizeBase: 1.915 m_fontWeight: 400 m_enableAutoSizing: 0 m_fontSizeMin: 18 m_fontSizeMax: 72 m_fontStyle: 0 - m_HorizontalAlignment: 1 - m_VerticalAlignment: 256 + m_HorizontalAlignment: 2 + m_VerticalAlignment: 512 m_textAlignment: 65535 m_characterSpacing: 0 m_wordSpacing: 0 @@ -2370,35 +2366,35 @@ MonoBehaviour: _SortingLayerID: 0 _SortingOrder: 0 m_hasFontAssetChanged: 0 - m_renderer: {fileID: 6060768737393671651} + m_renderer: {fileID: 4683226676648572474} m_maskType: 0 ---- !u!114 &3626078249338065464 +--- !u!114 &4801091935649164795 MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 3204955315311320290} + m_GameObject: {fileID: 2130932365216558288} m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 69beb381e244f92449b8c4cf954630e9, type: 3} m_Name: m_EditorClassIdentifier: m_TrackedObjects: - - rid: 8021623883140169743 + - rid: 3215294302546034854 references: version: 2 RefIds: - - rid: 8021623883140169743 + - rid: 3215294302546034854 type: {class: TrackedUGuiGraphic, ns: UnityEngine.Localization.PropertyVariants.TrackedObjects, asm: Unity.Localization} data: - m_Target: {fileID: 1725896781546607429} + m_Target: {fileID: 6232891306609240420} m_TrackedProperties: items: - - rid: 8021623883140169744 + - rid: 3215294302546034855 m_UpdateType: 0 - - rid: 8021623883140169744 + - rid: 3215294302546034855 type: {class: LocalizedStringProperty, ns: UnityEngine.Localization.PropertyVariants.TrackedProperties, asm: Unity.Localization} data: @@ -2406,13 +2402,13 @@ MonoBehaviour: m_TableReference: m_TableCollectionName: GUID:c84355079ab3f3e4f8f3812258805f86 m_TableEntryReference: - m_KeyId: 15531555001511936 + m_KeyId: 76138395621449728 m_Key: m_FallbackState: 0 m_WaitForCompletion: 0 m_LocalVariables: [] m_PropertyPath: m_text ---- !u!1 &3247850351716768939 +--- !u!1 &2181120061148835783 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -2420,51 +2416,84 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 6112888683899395240} - - component: {fileID: 6353905262143583131} - - component: {fileID: 1772275527878614484} - - component: {fileID: 216218237546220615} + - component: {fileID: 3457603883277620212} m_Layer: 16 - m_Name: Google_Text + m_Name: SketchfabInfoElements + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 0 +--- !u!4 &3457603883277620212 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2181120061148835783} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0.13499999, z: 0} + m_LocalScale: {x: 0.85, y: 0.8500001, z: 0.8500001} + m_ConstrainProportionsScale: 1 + m_Children: + - {fileID: 7650010300803901743} + - {fileID: 4704522903857296483} + - {fileID: 7338107887349877872} + m_Father: {fileID: 8645625734765961102} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &2524197670113838527 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1829480651769887961} + - component: {fileID: 3001700515688151744} + - component: {fileID: 1883450177596816156} + - component: {fileID: 5438294757481915153} + m_Layer: 16 + m_Name: Got it m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!224 &6112888683899395240 +--- !u!224 &1829480651769887961 RectTransform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 3247850351716768939} + m_GameObject: {fileID: 2524197670113838527} m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: -0.01} - m_LocalScale: {x: 1, y: 1, z: 1} + m_LocalPosition: {x: 0, y: 0, z: -0.029333334} + m_LocalScale: {x: 2.9528668, y: 5.9057336, z: 2.9528668} m_ConstrainProportionsScale: 0 m_Children: [] - m_Father: {fileID: 7741920746089690377} - m_RootOrder: 1 + m_Father: {fileID: 8645625735159627316} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} - m_AnchoredPosition: {x: -0.855, y: 0.3524501} - m_SizeDelta: {x: 0.52, y: 0.2} - m_Pivot: {x: 0, y: 1} ---- !u!23 &6353905262143583131 + m_AnchoredPosition: {x: 0.141, y: 0} + m_SizeDelta: {x: 0.25, y: 0.15} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!23 &3001700515688151744 MeshRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 3247850351716768939} + m_GameObject: {fileID: 2524197670113838527} m_Enabled: 1 m_CastShadows: 0 m_ReceiveShadows: 0 m_DynamicOccludee: 1 m_StaticShadowCaster: 0 m_MotionVectors: 1 - m_LightProbeUsage: 1 + m_LightProbeUsage: 0 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 m_RayTraceProcedural: 0 @@ -2483,7 +2512,7 @@ MeshRenderer: m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 - m_StitchLightmapSeams: 1 + m_StitchLightmapSeams: 0 m_SelectedEditorRenderState: 3 m_MinimumChartSize: 4 m_AutoUVMaxDistance: 0.5 @@ -2493,13 +2522,13 @@ MeshRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!114 &1772275527878614484 +--- !u!114 &1883450177596816156 MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 3247850351716768939} + m_GameObject: {fileID: 2524197670113838527} m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 9541d86e2fd84c1d9990edf0852d74ab, type: 3} @@ -2513,7 +2542,7 @@ MonoBehaviour: m_OnCullStateChanged: m_PersistentCalls: m_Calls: [] - m_text: Sign Out? + m_text: GOT IT m_isRightToLeft: 0 m_fontAsset: {fileID: 11400000, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} m_sharedMaterial: {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} @@ -2540,15 +2569,15 @@ MonoBehaviour: m_faceColor: serializedVersion: 2 rgba: 4294967295 - m_fontSize: 1.35 - m_fontSizeBase: 1.35 + m_fontSize: 0.64 + m_fontSizeBase: 0.64 m_fontWeight: 400 m_enableAutoSizing: 0 m_fontSizeMin: 18 m_fontSizeMax: 72 m_fontStyle: 0 - m_HorizontalAlignment: 1 - m_VerticalAlignment: 256 + m_HorizontalAlignment: 2 + m_VerticalAlignment: 512 m_textAlignment: 65535 m_characterSpacing: 0 m_wordSpacing: 0 @@ -2583,35 +2612,35 @@ MonoBehaviour: _SortingLayerID: 0 _SortingOrder: 0 m_hasFontAssetChanged: 0 - m_renderer: {fileID: 6353905262143583131} + m_renderer: {fileID: 3001700515688151744} m_maskType: 0 ---- !u!114 &216218237546220615 +--- !u!114 &5438294757481915153 MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 3247850351716768939} + m_GameObject: {fileID: 2524197670113838527} m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 69beb381e244f92449b8c4cf954630e9, type: 3} m_Name: m_EditorClassIdentifier: m_TrackedObjects: - - rid: 8021623883140169741 + - rid: 3215294302546034844 references: version: 2 RefIds: - - rid: 8021623883140169741 + - rid: 3215294302546034844 type: {class: TrackedUGuiGraphic, ns: UnityEngine.Localization.PropertyVariants.TrackedObjects, asm: Unity.Localization} data: - m_Target: {fileID: 1772275527878614484} + m_Target: {fileID: 1883450177596816156} m_TrackedProperties: items: - - rid: 8021623883140169742 + - rid: 3215294302546034845 m_UpdateType: 0 - - rid: 8021623883140169742 + - rid: 3215294302546034845 type: {class: LocalizedStringProperty, ns: UnityEngine.Localization.PropertyVariants.TrackedProperties, asm: Unity.Localization} data: @@ -2619,13 +2648,13 @@ MonoBehaviour: m_TableReference: m_TableCollectionName: GUID:c84355079ab3f3e4f8f3812258805f86 m_TableEntryReference: - m_KeyId: 15531555001511936 + m_KeyId: 76036746777255936 m_Key: m_FallbackState: 0 m_WaitForCompletion: 0 m_LocalVariables: [] m_PropertyPath: m_text ---- !u!1 &3251409475044903767 +--- !u!1 &2539912369590534119 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -2633,58 +2662,60 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 6454029799957143386} - - component: {fileID: 3129511076722104631} - - component: {fileID: 281154862723617330} - - component: {fileID: 9095323795036903516} + - component: {fileID: 8671432921432109627} + - component: {fileID: 2328370020170245272} + - component: {fileID: 3823398956549937895} m_Layer: 16 - m_Name: Got it + m_Name: Google_BackPlate m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!224 &6454029799957143386 -RectTransform: +--- !u!4 &8671432921432109627 +Transform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 3251409475044903767} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: -0.029333334} - m_LocalScale: {x: 2.9528668, y: 5.9057336, z: 2.9528668} + m_GameObject: {fileID: 2539912369590534119} + serializedVersion: 2 + m_LocalRotation: {x: -0.7071068, y: -0, z: -0, w: 0.7071067} + m_LocalPosition: {x: -0.7238, y: 0.2550001, z: -0.005} + m_LocalScale: {x: 32, y: 32, z: 20} m_ConstrainProportionsScale: 0 m_Children: [] - m_Father: {fileID: 7338107887349877872} - m_RootOrder: 0 + m_Father: {fileID: 1432546188030660464} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0.5, y: 0.5} - m_AnchorMax: {x: 0.5, y: 0.5} - m_AnchoredPosition: {x: 0.141, y: 0} - m_SizeDelta: {x: 0.25, y: 0.15} - m_Pivot: {x: 0.5, y: 0.5} ---- !u!23 &3129511076722104631 +--- !u!33 &2328370020170245272 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2539912369590534119} + m_Mesh: {fileID: 4300002, guid: 3efe5b86b55995545a231ce66a53b402, type: 3} +--- !u!23 &3823398956549937895 MeshRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 3251409475044903767} + m_GameObject: {fileID: 2539912369590534119} m_Enabled: 1 m_CastShadows: 0 m_ReceiveShadows: 0 m_DynamicOccludee: 1 m_StaticShadowCaster: 0 m_MotionVectors: 1 - m_LightProbeUsage: 0 + m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} + - {fileID: 2100000, guid: 8fe8230ee7ae32a4eb7fe6d5df34ebd4, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 @@ -2706,186 +2737,54 @@ MeshRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!114 &281154862723617330 -MonoBehaviour: +--- !u!1 &2541333487600552761 +GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 3251409475044903767} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 9541d86e2fd84c1d9990edf0852d74ab, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Material: {fileID: 0} - m_Color: {r: 1, g: 1, b: 1, a: 1} - m_RaycastTarget: 1 - m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} - m_Maskable: 1 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_text: GOT IT - m_isRightToLeft: 0 - m_fontAsset: {fileID: 11400000, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} - m_sharedMaterial: {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} - m_fontSharedMaterials: [] - m_fontMaterial: {fileID: 0} - m_fontMaterials: [] - m_fontColor32: - serializedVersion: 2 - rgba: 4294967295 - m_fontColor: {r: 1, g: 1, b: 1, a: 1} - m_enableVertexGradient: 0 - m_colorMode: 3 - m_fontColorGradient: - topLeft: {r: 1, g: 1, b: 1, a: 1} - topRight: {r: 1, g: 1, b: 1, a: 1} - bottomLeft: {r: 1, g: 1, b: 1, a: 1} - bottomRight: {r: 1, g: 1, b: 1, a: 1} - m_fontColorGradientPreset: {fileID: 0} - m_spriteAsset: {fileID: 0} - m_tintAllSprites: 0 - m_StyleSheet: {fileID: 0} - m_TextStyleHashCode: -1183493901 - m_overrideHtmlColors: 0 - m_faceColor: - serializedVersion: 2 - rgba: 4294967295 - m_fontSize: 0.64 - m_fontSizeBase: 0.64 - m_fontWeight: 400 - m_enableAutoSizing: 0 - m_fontSizeMin: 18 - m_fontSizeMax: 72 - m_fontStyle: 0 - m_HorizontalAlignment: 2 - m_VerticalAlignment: 512 - m_textAlignment: 65535 - m_characterSpacing: 0 - m_wordSpacing: 0 - m_lineSpacing: 0 - m_lineSpacingMax: 0 - m_paragraphSpacing: 0 - m_charWidthMaxAdj: 0 - m_enableWordWrapping: 1 - m_wordWrappingRatios: 0.4 - m_overflowMode: 0 - m_linkedTextComponent: {fileID: 0} - parentLinkedComponent: {fileID: 0} - m_enableKerning: 1 - m_enableExtraPadding: 0 - checkPaddingRequired: 0 - m_isRichText: 1 - m_parseCtrlCharacters: 1 - m_isOrthographic: 0 - m_isCullingEnabled: 0 - m_horizontalMapping: 0 - m_verticalMapping: 0 - m_uvLineOffset: 0 - m_geometrySortingOrder: 0 - m_IsTextObjectScaleStatic: 0 - m_VertexBufferAutoSizeReduction: 0 - m_useMaxVisibleDescender: 1 - m_pageToDisplay: 1 - m_margin: {x: 0, y: 0, z: 0, w: 0} - m_isUsingLegacyAnimationComponent: 0 - m_isVolumetricText: 0 - _SortingLayer: 0 - _SortingLayerID: 0 - _SortingOrder: 0 - m_hasFontAssetChanged: 0 - m_renderer: {fileID: 3129511076722104631} - m_maskType: 0 ---- !u!114 &9095323795036903516 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 3251409475044903767} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 69beb381e244f92449b8c4cf954630e9, type: 3} - m_Name: - m_EditorClassIdentifier: - m_TrackedObjects: - - rid: 3215294302546034844 - references: - version: 2 - RefIds: - - rid: 3215294302546034844 - type: {class: TrackedUGuiGraphic, ns: UnityEngine.Localization.PropertyVariants.TrackedObjects, - asm: Unity.Localization} - data: - m_Target: {fileID: 281154862723617330} - m_TrackedProperties: - items: - - rid: 3215294302546034845 - m_UpdateType: 0 - - rid: 3215294302546034845 - type: {class: LocalizedStringProperty, ns: UnityEngine.Localization.PropertyVariants.TrackedProperties, - asm: Unity.Localization} - data: - m_Localized: - m_TableReference: - m_TableCollectionName: GUID:c84355079ab3f3e4f8f3812258805f86 - m_TableEntryReference: - m_KeyId: 76036746777255936 - m_Key: - m_FallbackState: 0 - m_WaitForCompletion: 0 - m_LocalVariables: [] - m_PropertyPath: m_text ---- !u!1 &3350558357556252257 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 7580573523043848490} - - component: {fileID: 8140081930800988506} - - component: {fileID: 2514654466827372125} - m_Layer: 16 - m_Name: Background - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &7580573523043848490 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 3350558357556252257} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0.045} - m_LocalScale: {x: 2, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 181638217984195686} - m_RootOrder: 1 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!33 &8140081930800988506 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 3350558357556252257} - m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} ---- !u!23 &2514654466827372125 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 3350558357556252257} + serializedVersion: 6 + m_Component: + - component: {fileID: 4100876239645834569} + - component: {fileID: 7900905264382626932} + - component: {fileID: 6231791383006965005} + m_Layer: 16 + m_Name: MeshBackground + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4100876239645834569 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2541333487600552761} + serializedVersion: 2 + m_LocalRotation: {x: 0.7071068, y: -0, z: -0, w: 0.7071068} + m_LocalPosition: {x: 0, y: 0, z: 0.025} + m_LocalScale: {x: 0.79999995, y: 0.02, z: 0.8} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 5521146392998997215} + m_LocalEulerAnglesHint: {x: 90, y: 0, z: 0} +--- !u!33 &7900905264382626932 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2541333487600552761} + m_Mesh: {fileID: 10206, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &6231791383006965005 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2541333487600552761} m_Enabled: 1 m_CastShadows: 0 m_ReceiveShadows: 0 @@ -2899,7 +2798,7 @@ MeshRenderer: m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 2100000, guid: 0ead8b8e224bcf040862605f5eed7211, type: 2} + - {fileID: 2100000, guid: 77dd4ff8b1158a84397aba783cd0af05, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 @@ -2921,7 +2820,7 @@ MeshRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!1 &3387414818891217864 +--- !u!1 &2615357070484673490 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -2929,60 +2828,60 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 4946117081540083272} - - component: {fileID: 1555734638323418344} - - component: {fileID: 6328234730399420729} + - component: {fileID: 8245513620673000221} + - component: {fileID: 8539932158365628172} + - component: {fileID: 3222010795993119791} m_Layer: 16 - m_Name: Sketchfab_Logo + m_Name: Sketchfab_BackPlate m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!4 &4946117081540083272 +--- !u!4 &8245513620673000221 Transform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 3387414818891217864} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0.278, y: 0.26200008, z: -0.01} - m_LocalScale: {x: 0.2649999, y: 0.2649999, z: 0.2649999} + m_GameObject: {fileID: 2615357070484673490} + serializedVersion: 2 + m_LocalRotation: {x: -0.7071068, y: -0, z: -0, w: 0.7071067} + m_LocalPosition: {x: 0.622, y: 0.2550001, z: -0.005} + m_LocalScale: {x: 32, y: 32, z: 20} m_ConstrainProportionsScale: 0 m_Children: [] - m_Father: {fileID: 534589999851858800} - m_RootOrder: 1 + m_Father: {fileID: 6423827612944397798} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!33 &1555734638323418344 +--- !u!33 &8539932158365628172 MeshFilter: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 3387414818891217864} - m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} ---- !u!23 &6328234730399420729 + m_GameObject: {fileID: 2615357070484673490} + m_Mesh: {fileID: 4300002, guid: 3efe5b86b55995545a231ce66a53b402, type: 3} +--- !u!23 &3222010795993119791 MeshRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 3387414818891217864} + m_GameObject: {fileID: 2615357070484673490} m_Enabled: 1 m_CastShadows: 0 m_ReceiveShadows: 0 m_DynamicOccludee: 1 m_StaticShadowCaster: 0 m_MotionVectors: 1 - m_LightProbeUsage: 0 + m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 2100000, guid: 46140578835b4f14582726c5d76a6eda, type: 2} + - {fileID: 2100000, guid: 8fe8230ee7ae32a4eb7fe6d5df34ebd4, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 @@ -3004,7 +2903,7 @@ MeshRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!1 &3674036727267325941 +--- !u!1 &2675879709888175167 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -3012,64 +2911,56 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 5521146392998997215} - - component: {fileID: 3994049754972082256} - - component: {fileID: 619260971007631306} - - component: {fileID: 2495991278148453507} - - component: {fileID: 4355862344388155723} - m_Layer: 16 - m_Name: Button_ClosePopup + - component: {fileID: 90735575297890764} + - component: {fileID: 6241670906414567126} + - component: {fileID: 3509174102411407934} + m_Layer: 0 + m_Name: Sketchfab_Name m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!4 &5521146392998997215 -Transform: +--- !u!224 &90735575297890764 +RectTransform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 3674036727267325941} + m_GameObject: {fileID: 2675879709888175167} m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 1.251, y: -0.75199986, z: -0.018} - m_LocalScale: {x: 0.29999998, y: 0.29999998, z: 0.29999998} + m_LocalPosition: {x: 0, y: 0, z: -0.010000003} + m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 - m_Children: - - {fileID: 6855474239171570967} - - {fileID: 4100876239645834569} - m_Father: {fileID: 3576301794080265196} - m_RootOrder: 3 + m_Children: [] + m_Father: {fileID: 529827201699571093} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!33 &3994049754972082256 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 3674036727267325941} - m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} ---- !u!23 &619260971007631306 + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0.059, y: -0.477} + m_SizeDelta: {x: 1.1, y: 0.35} + m_Pivot: {x: 0, y: 0} +--- !u!23 &6241670906414567126 MeshRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 3674036727267325941} - m_Enabled: 0 + m_GameObject: {fileID: 2675879709888175167} + m_Enabled: 1 m_CastShadows: 0 m_ReceiveShadows: 0 m_DynamicOccludee: 1 m_StaticShadowCaster: 0 m_MotionVectors: 1 - m_LightProbeUsage: 0 + m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 2100000, guid: 3c8ca511828182747a0b79564892ec57, type: 2} + - {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 @@ -3091,99 +2982,99 @@ MeshRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!65 &2495991278148453507 -BoxCollider: +--- !u!114 &3509174102411407934 +MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 3674036727267325941} - m_Material: {fileID: 0} - m_IsTrigger: 0 - m_Enabled: 1 - serializedVersion: 2 - m_Size: {x: 1.0000001, y: 1, z: 0.01} - m_Center: {x: 0, y: 0, z: -0.01} ---- !u!114 &4355862344388155723 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 3674036727267325941} + m_GameObject: {fileID: 2675879709888175167} m_Enabled: 1 m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fc12adcafa62a22458e635d2ee7e78b5, type: 3} + m_Script: {fileID: 11500000, guid: 9541d86e2fd84c1d9990edf0852d74ab, type: 3} m_Name: m_EditorClassIdentifier: - m_DescriptionType: 0 - m_DescriptionYOffset: 0 - m_DescriptionText: Close - m_LocalizedDescription: - m_TableReference: - m_TableCollectionName: - m_TableEntryReference: - m_KeyId: 0 - m_Key: - m_FallbackState: 0 - m_WaitForCompletion: 0 - m_LocalVariables: [] - m_DescriptionTextExtra: - m_LocalizedDescriptionExtra: - m_TableReference: - m_TableCollectionName: - m_TableEntryReference: - m_KeyId: 0 - m_Key: - m_FallbackState: 0 - m_WaitForCompletion: 0 - m_LocalVariables: [] - m_DescriptionActivateSpeed: 12 - m_DescriptionZScale: 1 - m_ButtonTexture: {fileID: 0} - m_AtlasTexture: 0 - m_ToggleButton: 0 - m_LongPressReleaseButton: 0 - m_ButtonHasPressedAudio: 1 - m_ZAdjustHover: -0.02 - m_ZAdjustClick: 0.03 - m_HoverScale: 1.1 - m_HoverBoxColliderGrow: 0.2 - m_AddOverlay: 0 - m_Command: 0 - m_CommandParam: -1 - m_CommandParam2: -1 - m_RequiresPopup: 0 - m_CenterPopupOnButton: 0 - m_PopupOffset: {x: 0, y: 0, z: 0} - m_PopupText: - m_LocalizedPopup: - m_TableReference: - m_TableCollectionName: - m_TableEntryReference: - m_KeyId: 0 - m_Key: - m_FallbackState: 0 - m_WaitForCompletion: 0 - m_LocalVariables: [] - m_ToggleOnDescription: - m_LocalizedToggleOnDescription: - m_TableReference: - m_TableCollectionName: - m_TableEntryReference: - m_KeyId: 0 - m_Key: - m_FallbackState: 0 - m_WaitForCompletion: 0 - m_LocalVariables: [] - m_ToggleOnTexture: {fileID: 0} - m_AllowUnavailable: 0 - m_LinkedUIObject: {fileID: 0} - m_CommandIgnored: 0 - references: - version: 2 - RefIds: [] ---- !u!1 &3793285321450572269 + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_text: Longnamefirstname Longnamesurname + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} + m_sharedMaterial: {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4294967295 + m_fontColor: {r: 1, g: 1, b: 1, a: 1} + m_enableVertexGradient: 0 + m_colorMode: 3 + m_fontColorGradient: + topLeft: {r: 1, g: 1, b: 1, a: 1} + topRight: {r: 1, g: 1, b: 1, a: 1} + bottomLeft: {r: 1, g: 1, b: 1, a: 1} + bottomRight: {r: 1, g: 1, b: 1, a: 1} + m_fontColorGradientPreset: {fileID: 0} + m_spriteAsset: {fileID: 0} + m_tintAllSprites: 0 + m_StyleSheet: {fileID: 0} + m_TextStyleHashCode: -1183493901 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_fontSize: 1.3 + m_fontSizeBase: 1.3 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_HorizontalAlignment: 2 + m_VerticalAlignment: 256 + m_textAlignment: 65535 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: -22 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_enableWordWrapping: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 3 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 0 + m_isCullingEnabled: 0 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_IsTextObjectScaleStatic: 0 + m_VertexBufferAutoSizeReduction: 1 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + _SortingLayer: 0 + _SortingLayerID: 0 + _SortingOrder: 0 + m_hasFontAssetChanged: 0 + m_renderer: {fileID: 6241670906414567126} + m_maskType: 0 +--- !u!1 &2727968127303647375 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -3191,60 +3082,60 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 6855474239171570967} - - component: {fileID: 4593108259088090395} - - component: {fileID: 1617028310973550690} + - component: {fileID: 4153333614772809210} + - component: {fileID: 3359518694211327191} + - component: {fileID: 6165908306739578010} m_Layer: 16 - m_Name: Mesh + m_Name: IconDriveFull m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &6855474239171570967 + m_IsActive: 0 +--- !u!4 &4153333614772809210 Transform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 3793285321450572269} + m_GameObject: {fileID: 2727968127303647375} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 0.65, y: 0.65, z: 1} + m_LocalPosition: {x: -0.33714277, y: -0.011110305, z: -0.024999999} + m_LocalScale: {x: 0.21428569, y: 0.8333332, z: 0.15} m_ConstrainProportionsScale: 0 m_Children: [] - m_Father: {fileID: 5521146392998997215} - m_RootOrder: 0 + m_Father: {fileID: 1741904442304953456} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!33 &4593108259088090395 +--- !u!33 &3359518694211327191 MeshFilter: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 3793285321450572269} + m_GameObject: {fileID: 2727968127303647375} m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} ---- !u!23 &1617028310973550690 +--- !u!23 &6165908306739578010 MeshRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 3793285321450572269} + m_GameObject: {fileID: 2727968127303647375} m_Enabled: 1 m_CastShadows: 0 m_ReceiveShadows: 0 m_DynamicOccludee: 1 m_StaticShadowCaster: 0 m_MotionVectors: 1 - m_LightProbeUsage: 1 + m_LightProbeUsage: 0 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 2100000, guid: 0d7eb02b18ffb4c419fb75924cb900dc, type: 2} + - {fileID: 2100000, guid: 9cad1001e55b6a34083acc3b00f3a2aa, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 @@ -3253,7 +3144,7 @@ MeshRenderer: m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 m_ReceiveGI: 1 - m_PreserveUVs: 1 + m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 m_StitchLightmapSeams: 0 @@ -3266,7 +3157,7 @@ MeshRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!1 &3883720175326442003 +--- !u!1 &2777064628006719104 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -3274,47 +3165,51 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 6692607038900794975} - - component: {fileID: 1080627186782362197} - - component: {fileID: 2964682892386166551} + - component: {fileID: 181638217984195686} + - component: {fileID: 4757421857253066679} + - component: {fileID: 28647745892822175} + - component: {fileID: 8171971593979727739} + - component: {fileID: 811447535104194712} m_Layer: 16 - m_Name: Google_BackPlate + m_Name: Sketchfab_SignIn m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!4 &6692607038900794975 +--- !u!4 &181638217984195686 Transform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 3883720175326442003} - m_LocalRotation: {x: -0.7071068, y: -0, z: -0, w: 0.7071067} - m_LocalPosition: {x: -0.621, y: -0.151, z: -0.005} - m_LocalScale: {x: 47, y: 49.999924, z: 74.2} + m_GameObject: {fileID: 2777064628006719104} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0.627, y: -0.242, z: -0.06} + m_LocalScale: {x: 0.4, y: 0.4, z: 0.4} m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 1411852402157678472} - m_RootOrder: 4 + m_Children: + - {fileID: 3376029733079660750} + - {fileID: 7580573523043848490} + m_Father: {fileID: 534589999851858800} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!33 &1080627186782362197 +--- !u!33 &4757421857253066679 MeshFilter: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 3883720175326442003} - m_Mesh: {fileID: 4300002, guid: 3efe5b86b55995545a231ce66a53b402, type: 3} ---- !u!23 &2964682892386166551 + m_GameObject: {fileID: 2777064628006719104} + m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &28647745892822175 MeshRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 3883720175326442003} - m_Enabled: 1 + m_GameObject: {fileID: 2777064628006719104} + m_Enabled: 0 m_CastShadows: 0 m_ReceiveShadows: 0 m_DynamicOccludee: 1 @@ -3327,7 +3222,7 @@ MeshRenderer: m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 2100000, guid: 8fe8230ee7ae32a4eb7fe6d5df34ebd4, type: 2} + - {fileID: 2100000, guid: 005edae3a0d4d1243ba88ed7543cd61d, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 @@ -3336,7 +3231,7 @@ MeshRenderer: m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 m_ReceiveGI: 1 - m_PreserveUVs: 0 + m_PreserveUVs: 1 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 m_StitchLightmapSeams: 0 @@ -3349,132 +3244,13 @@ MeshRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!1 &4082436277880791083 -GameObject: +--- !u!114 &8171971593979727739 +MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 5854179938074699431} - m_Layer: 16 - m_Name: Google - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &5854179938074699431 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4082436277880791083} - 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_ConstrainProportionsScale: 0 - m_Children: - - {fileID: 1411852402157678472} - - {fileID: 1432546188030660464} - - {fileID: 7741920746089690377} - m_Father: {fileID: 8645625735416266758} - m_RootOrder: 2 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &4103205528941609404 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 4700142148089133932} - - component: {fileID: 3380311651882997193} - - component: {fileID: 4297529096568456498} - - component: {fileID: 5219542430503434550} - - component: {fileID: 586799646275115208} - m_Layer: 16 - m_Name: Sketchfab_Info - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &4700142148089133932 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4103205528941609404} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 1.046, y: 0.2620001, z: -0.025} - m_LocalScale: {x: 0.2, y: 0.2, z: 0.2} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 534589999851858800} - m_RootOrder: 3 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!33 &3380311651882997193 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4103205528941609404} - m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} ---- !u!23 &4297529096568456498 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4103205528941609404} - m_Enabled: 1 - m_CastShadows: 0 - m_ReceiveShadows: 0 - m_DynamicOccludee: 1 - m_StaticShadowCaster: 0 - m_MotionVectors: 1 - m_LightProbeUsage: 0 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RayTraceProcedural: 0 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 2100000, guid: 3c8ca511828182747a0b79564892ec57, type: 2} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 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 - m_AdditionalVertexStreams: {fileID: 0} ---- !u!114 &5219542430503434550 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4103205528941609404} + m_GameObject: {fileID: 2777064628006719104} m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: fc12adcafa62a22458e635d2ee7e78b5, type: 3} @@ -3504,17 +3280,17 @@ MonoBehaviour: m_LocalVariables: [] m_DescriptionActivateSpeed: 12 m_DescriptionZScale: 1 - m_ButtonTexture: {fileID: 2800000, guid: bb4439b4279219b4db937c93530893ff, type: 3} - m_AtlasTexture: 1 + m_ButtonTexture: {fileID: 0} + m_AtlasTexture: 0 m_ToggleButton: 0 m_LongPressReleaseButton: 0 m_ButtonHasPressedAudio: 1 m_ZAdjustHover: -0.02 m_ZAdjustClick: 0.05 - m_HoverScale: 1.2 + m_HoverScale: 1.1 m_HoverBoxColliderGrow: 0.2 m_AddOverlay: 0 - m_Command: 73 + m_Command: 95 m_CommandParam: 2 m_CommandParam2: -1 m_RequiresPopup: 0 @@ -3541,26 +3317,34 @@ MonoBehaviour: m_WaitForCompletion: 0 m_LocalVariables: [] m_ToggleOnTexture: {fileID: 0} - m_AllowUnavailable: 0 + m_AllowUnavailable: 1 m_LinkedUIObject: {fileID: 0} m_CommandIgnored: 0 references: version: 2 RefIds: [] ---- !u!65 &586799646275115208 +--- !u!65 &811447535104194712 BoxCollider: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4103205528941609404} + m_GameObject: {fileID: 2777064628006719104} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 - m_Size: {x: 1, y: 1.0000001, z: 0.1} + serializedVersion: 3 + m_Size: {x: 2, y: 1.0000001, z: 0.1} m_Center: {x: 0, y: 0, z: -0.01} ---- !u!1 &4105427794534146856 +--- !u!1 &3011044884306177928 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -3568,48 +3352,46 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 4120900520909079457} - - component: {fileID: 4957999687296029088} - - component: {fileID: 6324396148345559707} - - component: {fileID: 5104710591034478679} - - component: {fileID: 7087448018191981113} + - component: {fileID: 8939772953772003517} + - component: {fileID: 1159919028371824209} + - component: {fileID: 657338479228588091} m_Layer: 16 - m_Name: Sketchfab_Cancel + m_Name: Icosa_BackPlate m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!4 &4120900520909079457 +--- !u!4 &8939772953772003517 Transform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4105427794534146856} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0.398, y: -0.242, z: -0.06} - m_LocalScale: {x: 0.35, y: 0.35, z: 0.35} + m_GameObject: {fileID: 3011044884306177928} + serializedVersion: 2 + m_LocalRotation: {x: -0.7071068, y: -0, z: -0, w: 0.7071067} + m_LocalPosition: {x: 0.622, y: 0.2550001, z: -0.005} + m_LocalScale: {x: 32, y: 32, z: 20} m_ConstrainProportionsScale: 0 m_Children: [] - m_Father: {fileID: 6423827612944397798} - m_RootOrder: 3 + m_Father: {fileID: 1675920430848132177} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!33 &4957999687296029088 +--- !u!33 &1159919028371824209 MeshFilter: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4105427794534146856} - m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} ---- !u!23 &6324396148345559707 + m_GameObject: {fileID: 3011044884306177928} + m_Mesh: {fileID: 4300002, guid: 3efe5b86b55995545a231ce66a53b402, type: 3} +--- !u!23 &657338479228588091 MeshRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4105427794534146856} + m_GameObject: {fileID: 3011044884306177928} m_Enabled: 1 m_CastShadows: 0 m_ReceiveShadows: 0 @@ -3623,7 +3405,7 @@ MeshRenderer: m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 2100000, guid: 40d29de2bdc11f04dbfa25059165916e, type: 2} + - {fileID: 2100000, guid: 8fe8230ee7ae32a4eb7fe6d5df34ebd4, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 @@ -3632,7 +3414,7 @@ MeshRenderer: m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 m_ReceiveGI: 1 - m_PreserveUVs: 1 + m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 m_StitchLightmapSeams: 0 @@ -3645,99 +3427,7 @@ MeshRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!114 &5104710591034478679 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4105427794534146856} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fc12adcafa62a22458e635d2ee7e78b5, type: 3} - m_Name: - m_EditorClassIdentifier: - m_DescriptionType: 0 - m_DescriptionYOffset: 0 - m_DescriptionText: Cancel - m_LocalizedDescription: - m_TableReference: - m_TableCollectionName: GUID:c84355079ab3f3e4f8f3812258805f86 - m_TableEntryReference: - m_KeyId: 15526523405381632 - m_Key: - m_FallbackState: 0 - m_WaitForCompletion: 0 - m_LocalVariables: [] - m_DescriptionTextExtra: - m_LocalizedDescriptionExtra: - m_TableReference: - m_TableCollectionName: - m_TableEntryReference: - m_KeyId: 0 - m_Key: - m_FallbackState: 0 - m_WaitForCompletion: 0 - m_LocalVariables: [] - m_DescriptionActivateSpeed: 12 - m_DescriptionZScale: 1 - m_ButtonTexture: {fileID: 2800000, guid: 957f69e59565cd1469fa095b415fa513, type: 3} - m_AtlasTexture: 0 - m_ToggleButton: 0 - m_LongPressReleaseButton: 0 - m_ButtonHasPressedAudio: 1 - m_ZAdjustHover: -0.02 - m_ZAdjustClick: 0.05 - m_HoverScale: 1.1 - m_HoverBoxColliderGrow: 0.2 - m_AddOverlay: 0 - m_Command: 0 - m_CommandParam: 2 - m_CommandParam2: -1 - m_RequiresPopup: 0 - m_CenterPopupOnButton: 0 - m_PopupOffset: {x: 0, y: 0, z: 0} - m_PopupText: - m_LocalizedPopup: - m_TableReference: - m_TableCollectionName: - m_TableEntryReference: - m_KeyId: 0 - m_Key: - m_FallbackState: 0 - m_WaitForCompletion: 0 - m_LocalVariables: [] - m_ToggleOnDescription: - m_LocalizedToggleOnDescription: - m_TableReference: - m_TableCollectionName: - m_TableEntryReference: - m_KeyId: 0 - m_Key: - m_FallbackState: 0 - m_WaitForCompletion: 0 - m_LocalVariables: [] - m_ToggleOnTexture: {fileID: 0} - m_AllowUnavailable: 0 - m_LinkedUIObject: {fileID: 0} - m_CommandIgnored: 1 - references: - version: 2 - RefIds: [] ---- !u!65 &7087448018191981113 -BoxCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4105427794534146856} - m_Material: {fileID: 0} - m_IsTrigger: 0 - m_Enabled: 1 - serializedVersion: 2 - m_Size: {x: 1, y: 1.0000001, z: 0.1} - m_Center: {x: 0, y: 0, z: -0.01} ---- !u!1 &4316944982740412120 +--- !u!1 &3204955315311320290 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -3745,210 +3435,43 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 1180802039870758397} - - component: {fileID: 390951240049198343} - - component: {fileID: 6026671568046064672} + - component: {fileID: 4111961635044152573} + - component: {fileID: 6060768737393671651} + - component: {fileID: 1725896781546607429} + - component: {fileID: 3626078249338065464} m_Layer: 16 - m_Name: IconDisabled + m_Name: Sketchfab_Text m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!4 &1180802039870758397 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4316944982740412120} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: -0.33714277, y: -0.011110305, z: -0.024999999} - m_LocalScale: {x: 0.21428569, y: 0.8333332, z: 0.15} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 1741904442304953456} - m_RootOrder: 1 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!33 &390951240049198343 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4316944982740412120} - m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} ---- !u!23 &6026671568046064672 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4316944982740412120} - m_Enabled: 1 - m_CastShadows: 0 - m_ReceiveShadows: 0 - m_DynamicOccludee: 1 - m_StaticShadowCaster: 0 - m_MotionVectors: 1 - m_LightProbeUsage: 0 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RayTraceProcedural: 0 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 2100000, guid: 6b65e04b1b7fb5644862eb36bfcfb419, type: 2} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 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 - m_AdditionalVertexStreams: {fileID: 0} ---- !u!1 &4539008613640430378 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 6661346418304443125} - - component: {fileID: 8976936997367820456} - - component: {fileID: 8201886566812613733} - m_Layer: 16 - m_Name: Sketchfab_Logo - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &6661346418304443125 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4539008613640430378} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0.37, y: -0.324, z: -0.025} - m_LocalScale: {x: 0.4, y: 0.4, z: 0.4} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 5621771514230647440} - m_RootOrder: 1 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!33 &8976936997367820456 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4539008613640430378} - m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} ---- !u!23 &8201886566812613733 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4539008613640430378} - m_Enabled: 1 - m_CastShadows: 0 - m_ReceiveShadows: 0 - m_DynamicOccludee: 1 - m_StaticShadowCaster: 0 - m_MotionVectors: 1 - m_LightProbeUsage: 0 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RayTraceProcedural: 0 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 2100000, guid: 46140578835b4f14582726c5d76a6eda, type: 2} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 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 - m_AdditionalVertexStreams: {fileID: 0} ---- !u!1 &4884541372955623633 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 7758143906596955047} - - component: {fileID: 3414497333256173795} - - component: {fileID: 7198143098074655042} - - component: {fileID: 1849472563075584265} - m_Layer: 16 - m_Name: Text - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!224 &7758143906596955047 +--- !u!224 &4111961635044152573 RectTransform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4884541372955623633} + m_GameObject: {fileID: 3204955315311320290} m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: -0.023000002} - m_LocalScale: {x: 1.7142857, y: 6.6666627, z: 0.8571429} + m_LocalPosition: {x: 0, y: 0, z: -0.01} + m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] - m_Father: {fileID: 1741904442304953456} - m_RootOrder: 3 + m_Father: {fileID: 6423827612944397798} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} - m_AnchoredPosition: {x: -0.183, y: -0.019} - m_SizeDelta: {x: 0.4, y: 0.1} - m_Pivot: {x: 0, y: 0.5} ---- !u!23 &3414497333256173795 + m_AnchoredPosition: {x: 0.429, y: 0.3524501} + m_SizeDelta: {x: 0.52, y: 0.2} + m_Pivot: {x: 0, y: 1} +--- !u!23 &6060768737393671651 MeshRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4884541372955623633} + m_GameObject: {fileID: 3204955315311320290} m_Enabled: 1 m_CastShadows: 0 m_ReceiveShadows: 0 @@ -3984,13 +3507,13 @@ MeshRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!114 &7198143098074655042 +--- !u!114 &1725896781546607429 MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4884541372955623633} + m_GameObject: {fileID: 3204955315311320290} m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 9541d86e2fd84c1d9990edf0852d74ab, type: 3} @@ -4004,7 +3527,7 @@ MonoBehaviour: m_OnCullStateChanged: m_PersistentCalls: m_Calls: [] - m_text: Drive Backup + m_text: Sign Out? m_isRightToLeft: 0 m_fontAsset: {fileID: 11400000, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} m_sharedMaterial: {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} @@ -4031,15 +3554,15 @@ MonoBehaviour: m_faceColor: serializedVersion: 2 rgba: 4294967295 - m_fontSize: 0.785 - m_fontSizeBase: 0.785 + m_fontSize: 1.35 + m_fontSizeBase: 1.35 m_fontWeight: 400 m_enableAutoSizing: 0 m_fontSizeMin: 18 m_fontSizeMax: 72 m_fontStyle: 0 m_HorizontalAlignment: 1 - m_VerticalAlignment: 512 + m_VerticalAlignment: 256 m_textAlignment: 65535 m_characterSpacing: 0 m_wordSpacing: 0 @@ -4074,35 +3597,35 @@ MonoBehaviour: _SortingLayerID: 0 _SortingOrder: 0 m_hasFontAssetChanged: 0 - m_renderer: {fileID: 3414497333256173795} + m_renderer: {fileID: 6060768737393671651} m_maskType: 0 ---- !u!114 &1849472563075584265 +--- !u!114 &3626078249338065464 MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 4884541372955623633} + m_GameObject: {fileID: 3204955315311320290} m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 69beb381e244f92449b8c4cf954630e9, type: 3} m_Name: m_EditorClassIdentifier: m_TrackedObjects: - - rid: 8021623883140169739 + - rid: 8021623883140169743 references: version: 2 RefIds: - - rid: 8021623883140169739 + - rid: 8021623883140169743 type: {class: TrackedUGuiGraphic, ns: UnityEngine.Localization.PropertyVariants.TrackedObjects, asm: Unity.Localization} data: - m_Target: {fileID: 7198143098074655042} + m_Target: {fileID: 1725896781546607429} m_TrackedProperties: items: - - rid: 8021623883140169740 + - rid: 8021623883140169744 m_UpdateType: 0 - - rid: 8021623883140169740 + - rid: 8021623883140169744 type: {class: LocalizedStringProperty, ns: UnityEngine.Localization.PropertyVariants.TrackedProperties, asm: Unity.Localization} data: @@ -4110,13 +3633,13 @@ MonoBehaviour: m_TableReference: m_TableCollectionName: GUID:c84355079ab3f3e4f8f3812258805f86 m_TableEntryReference: - m_KeyId: 15524391402909696 + m_KeyId: 15531555001511936 m_Key: m_FallbackState: 0 m_WaitForCompletion: 0 m_LocalVariables: [] m_PropertyPath: m_text ---- !u!1 &5048206632594256402 +--- !u!1 &3247850351716768939 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -4124,47 +3647,211 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 3576301794080265196} - - component: {fileID: 480163635885148388} + - component: {fileID: 6112888683899395240} + - component: {fileID: 6353905262143583131} + - component: {fileID: 1772275527878614484} + - component: {fileID: 216218237546220615} m_Layer: 16 - m_Name: DriveInfoElements + m_Name: Google_Text m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 - m_IsActive: 0 ---- !u!4 &3576301794080265196 -Transform: + m_IsActive: 1 +--- !u!224 &6112888683899395240 +RectTransform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5048206632594256402} + m_GameObject: {fileID: 3247850351716768939} m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalPosition: {x: 0, y: 0, z: -0.01} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 - m_Children: - - {fileID: 3755039154609302241} - - {fileID: 6679582736177907422} - - {fileID: 7566473728865432861} - - {fileID: 5521146392998997215} - m_Father: {fileID: 8645625734765961102} - m_RootOrder: 3 + m_Children: [] + m_Father: {fileID: 7741920746089690377} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!114 &480163635885148388 -MonoBehaviour: + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: -0.855, y: 0.3524501} + m_SizeDelta: {x: 0.52, y: 0.2} + m_Pivot: {x: 0, y: 1} +--- !u!23 &6353905262143583131 +MeshRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5048206632594256402} + m_GameObject: {fileID: 3247850351716768939} m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 20ac3005e19346a4296a8f6a73363832, type: 3} + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + 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 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!114 &1772275527878614484 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3247850351716768939} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 9541d86e2fd84c1d9990edf0852d74ab, type: 3} m_Name: m_EditorClassIdentifier: ---- !u!1 &5111218671440306906 + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_text: Sign Out? + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} + m_sharedMaterial: {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4294967295 + m_fontColor: {r: 1, g: 1, b: 1, a: 1} + m_enableVertexGradient: 0 + m_colorMode: 3 + m_fontColorGradient: + topLeft: {r: 1, g: 1, b: 1, a: 1} + topRight: {r: 1, g: 1, b: 1, a: 1} + bottomLeft: {r: 1, g: 1, b: 1, a: 1} + bottomRight: {r: 1, g: 1, b: 1, a: 1} + m_fontColorGradientPreset: {fileID: 0} + m_spriteAsset: {fileID: 0} + m_tintAllSprites: 0 + m_StyleSheet: {fileID: 0} + m_TextStyleHashCode: -1183493901 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_fontSize: 1.35 + m_fontSizeBase: 1.35 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_HorizontalAlignment: 1 + m_VerticalAlignment: 256 + m_textAlignment: 65535 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_enableWordWrapping: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 0 + m_isCullingEnabled: 0 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_IsTextObjectScaleStatic: 0 + m_VertexBufferAutoSizeReduction: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + _SortingLayer: 0 + _SortingLayerID: 0 + _SortingOrder: 0 + m_hasFontAssetChanged: 0 + m_renderer: {fileID: 6353905262143583131} + m_maskType: 0 +--- !u!114 &216218237546220615 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3247850351716768939} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 69beb381e244f92449b8c4cf954630e9, type: 3} + m_Name: + m_EditorClassIdentifier: + m_TrackedObjects: + - rid: 8021623883140169741 + references: + version: 2 + RefIds: + - rid: 8021623883140169741 + type: {class: TrackedUGuiGraphic, ns: UnityEngine.Localization.PropertyVariants.TrackedObjects, + asm: Unity.Localization} + data: + m_Target: {fileID: 1772275527878614484} + m_TrackedProperties: + items: + - rid: 8021623883140169742 + m_UpdateType: 0 + - rid: 8021623883140169742 + type: {class: LocalizedStringProperty, ns: UnityEngine.Localization.PropertyVariants.TrackedProperties, + asm: Unity.Localization} + data: + m_Localized: + m_TableReference: + m_TableCollectionName: GUID:c84355079ab3f3e4f8f3812258805f86 + m_TableEntryReference: + m_KeyId: 15531555001511936 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_PropertyPath: m_text +--- !u!1 &3251409475044903767 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -4172,44 +3859,43 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 9209058213459650767} - - component: {fileID: 8820378468166149913} - - component: {fileID: 1547790019101272354} - - component: {fileID: 3197312481833515046} - m_Layer: 0 - m_Name: Title + - component: {fileID: 6454029799957143386} + - component: {fileID: 3129511076722104631} + - component: {fileID: 281154862723617330} + - component: {fileID: 9095323795036903516} + m_Layer: 16 + m_Name: Got it m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!224 &9209058213459650767 +--- !u!224 &6454029799957143386 RectTransform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5111218671440306906} + m_GameObject: {fileID: 3251409475044903767} m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: -0.0025} - m_LocalScale: {x: 1, y: 1, z: 1} + m_LocalPosition: {x: 0, y: 0, z: -0.029333334} + m_LocalScale: {x: 2.9528668, y: 5.9057336, z: 2.9528668} m_ConstrainProportionsScale: 0 m_Children: [] - m_Father: {fileID: 4825048073929942150} - m_RootOrder: 0 + m_Father: {fileID: 7338107887349877872} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} - m_AnchoredPosition: {x: 0, y: 0.5} - m_SizeDelta: {x: 2.27, y: 0.3} + m_AnchoredPosition: {x: 0.141, y: 0} + m_SizeDelta: {x: 0.25, y: 0.15} m_Pivot: {x: 0.5, y: 0.5} ---- !u!23 &8820378468166149913 +--- !u!23 &3129511076722104631 MeshRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5111218671440306906} + m_GameObject: {fileID: 3251409475044903767} m_Enabled: 1 m_CastShadows: 0 m_ReceiveShadows: 0 @@ -4245,13 +3931,13 @@ MeshRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!114 &1547790019101272354 +--- !u!114 &281154862723617330 MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5111218671440306906} + m_GameObject: {fileID: 3251409475044903767} m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 9541d86e2fd84c1d9990edf0852d74ab, type: 3} @@ -4265,7 +3951,7 @@ MonoBehaviour: m_OnCullStateChanged: m_PersistentCalls: m_Calls: [] - m_text: Share with Google + m_text: GOT IT m_isRightToLeft: 0 m_fontAsset: {fileID: 11400000, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} m_sharedMaterial: {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} @@ -4292,8 +3978,8 @@ MonoBehaviour: m_faceColor: serializedVersion: 2 rgba: 4294967295 - m_fontSize: 1.915 - m_fontSizeBase: 1.915 + m_fontSize: 0.64 + m_fontSizeBase: 0.64 m_fontWeight: 400 m_enableAutoSizing: 0 m_fontSizeMin: 18 @@ -4335,35 +4021,35 @@ MonoBehaviour: _SortingLayerID: 0 _SortingOrder: 0 m_hasFontAssetChanged: 0 - m_renderer: {fileID: 8820378468166149913} + m_renderer: {fileID: 3129511076722104631} m_maskType: 0 ---- !u!114 &3197312481833515046 +--- !u!114 &9095323795036903516 MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5111218671440306906} + m_GameObject: {fileID: 3251409475044903767} m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 69beb381e244f92449b8c4cf954630e9, type: 3} m_Name: m_EditorClassIdentifier: m_TrackedObjects: - - rid: 3215294302546034850 + - rid: 3215294302546034844 references: version: 2 RefIds: - - rid: 3215294302546034850 + - rid: 3215294302546034844 type: {class: TrackedUGuiGraphic, ns: UnityEngine.Localization.PropertyVariants.TrackedObjects, asm: Unity.Localization} data: - m_Target: {fileID: 1547790019101272354} + m_Target: {fileID: 281154862723617330} m_TrackedProperties: items: - - rid: 3215294302546034851 + - rid: 3215294302546034845 m_UpdateType: 0 - - rid: 3215294302546034851 + - rid: 3215294302546034845 type: {class: LocalizedStringProperty, ns: UnityEngine.Localization.PropertyVariants.TrackedProperties, asm: Unity.Localization} data: @@ -4371,13 +4057,13 @@ MonoBehaviour: m_TableReference: m_TableCollectionName: GUID:c84355079ab3f3e4f8f3812258805f86 m_TableEntryReference: - m_KeyId: 76137928887689216 + m_KeyId: 76036746777255936 m_Key: m_FallbackState: 0 m_WaitForCompletion: 0 m_LocalVariables: [] m_PropertyPath: m_text ---- !u!1 &5123262806756250226 +--- !u!1 &3270184853410304968 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -4385,47 +4071,51 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 5208561973859313428} - - component: {fileID: 7929569316632562742} - - component: {fileID: 8052510225724890313} + - component: {fileID: 5520953697447238279} + - component: {fileID: 5249507884336548187} + - component: {fileID: 3255885207901872536} + - component: {fileID: 1824715322301957706} + - component: {fileID: 3327138301261596308} m_Layer: 16 - m_Name: Background + m_Name: Icosa_SignIn m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!4 &5208561973859313428 +--- !u!4 &5520953697447238279 Transform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5123262806756250226} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0.045} - m_LocalScale: {x: 2, y: 1, z: 1} + m_GameObject: {fileID: 3270184853410304968} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0.627, y: -0.242, z: -0.06} + m_LocalScale: {x: 0.4, y: 0.4, z: 0.4} m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 7893921961113671483} - m_RootOrder: 1 + m_Children: + - {fileID: 2729332839612941327} + - {fileID: 906844544403122228} + m_Father: {fileID: 1000721931266647293} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!33 &7929569316632562742 +--- !u!33 &5249507884336548187 MeshFilter: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5123262806756250226} + m_GameObject: {fileID: 3270184853410304968} m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} ---- !u!23 &8052510225724890313 +--- !u!23 &3255885207901872536 MeshRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5123262806756250226} - m_Enabled: 1 + m_GameObject: {fileID: 3270184853410304968} + m_Enabled: 0 m_CastShadows: 0 m_ReceiveShadows: 0 m_DynamicOccludee: 1 @@ -4438,7 +4128,7 @@ MeshRenderer: m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 2100000, guid: 0ead8b8e224bcf040862605f5eed7211, type: 2} + - {fileID: 2100000, guid: 005edae3a0d4d1243ba88ed7543cd61d, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 @@ -4460,68 +4150,172 @@ MeshRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!1 &5301811399408650331 -GameObject: +--- !u!114 &1824715322301957706 +MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1182483975005714860} - - component: {fileID: 6161329202685458175} - - component: {fileID: 6793863180280690477} - m_Layer: 16 - m_Name: Dividor + m_GameObject: {fileID: 3270184853410304968} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fc12adcafa62a22458e635d2ee7e78b5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_DescriptionType: -1 + m_DescriptionYOffset: 0 + m_DescriptionText: + m_LocalizedDescription: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_DescriptionTextExtra: + m_LocalizedDescriptionExtra: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_DescriptionActivateSpeed: 12 + m_DescriptionZScale: 1 + m_ButtonTexture: {fileID: 0} + m_AtlasTexture: 0 + m_ToggleButton: 0 + m_LongPressReleaseButton: 0 + m_ButtonHasPressedAudio: 1 + m_ZAdjustHover: -0.02 + m_ZAdjustClick: 0.05 + m_HoverScale: 1.1 + m_HoverBoxColliderGrow: 0.2 + m_AddOverlay: 0 + m_Command: 5600 + m_CommandParam: 3 + m_CommandParam2: -1 + m_RequiresPopup: 0 + m_CenterPopupOnButton: 0 + m_PopupOffset: {x: 0, y: 0, z: 0} + m_PopupText: + m_LocalizedPopup: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_ToggleOnDescription: + m_LocalizedToggleOnDescription: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_ToggleOnTexture: {fileID: 0} + m_AllowUnavailable: 1 + m_LinkedUIObject: {fileID: 0} + m_CommandIgnored: 0 + references: + version: 2 + RefIds: [] +--- !u!65 &3327138301261596308 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3270184853410304968} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Size: {x: 2, y: 1.0000001, z: 0.1} + m_Center: {x: 0, y: 0, z: -0.01} +--- !u!1 &3292774118003760337 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 7500850895307564819} + - component: {fileID: 6391502674584969794} + - component: {fileID: 588537084669385653} + - component: {fileID: 9061423159326835474} + - component: {fileID: 4927931040837201254} + m_Layer: 14 + m_Name: ConfirmationButton m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!4 &1182483975005714860 +--- !u!4 &7500850895307564819 Transform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5301811399408650331} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: -0.151, z: -0.005} - m_LocalScale: {x: 0.01, y: 1, z: 1} + m_GameObject: {fileID: 3292774118003760337} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: -0.434, z: -0.08} + m_LocalScale: {x: 0.6, y: 0.29999998, z: 0.29999998} m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 8645625735416266758} - m_RootOrder: 1 + m_Children: + - {fileID: 4750169147585981226} + - {fileID: 2257200555475620437} + m_Father: {fileID: 6373137851377895237} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!33 &6161329202685458175 +--- !u!33 &6391502674584969794 MeshFilter: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5301811399408650331} + m_GameObject: {fileID: 3292774118003760337} m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} ---- !u!23 &6793863180280690477 +--- !u!23 &588537084669385653 MeshRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5301811399408650331} - m_Enabled: 1 + m_GameObject: {fileID: 3292774118003760337} + m_Enabled: 0 m_CastShadows: 0 m_ReceiveShadows: 0 m_DynamicOccludee: 1 m_StaticShadowCaster: 0 m_MotionVectors: 1 - m_LightProbeUsage: 1 + m_LightProbeUsage: 0 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 2100000, guid: 8fe8230ee7ae32a4eb7fe6d5df34ebd4, type: 2} + - {fileID: 2100000, guid: 3c8ca511828182747a0b79564892ec57, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 @@ -4543,7 +4337,107 @@ MeshRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!1 &5315453881601467229 +--- !u!65 &9061423159326835474 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3292774118003760337} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Size: {x: 1, y: 1, z: 0.01} + m_Center: {x: 0, y: 0, z: -0.01} +--- !u!114 &4927931040837201254 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3292774118003760337} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fc12adcafa62a22458e635d2ee7e78b5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_DescriptionType: -1 + m_DescriptionYOffset: 0 + m_DescriptionText: + m_LocalizedDescription: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_DescriptionTextExtra: + m_LocalizedDescriptionExtra: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_DescriptionActivateSpeed: 12 + m_DescriptionZScale: 1 + m_ButtonTexture: {fileID: 0} + m_AtlasTexture: 0 + m_ToggleButton: 0 + m_LongPressReleaseButton: 0 + m_ButtonHasPressedAudio: 1 + m_ZAdjustHover: -0.02 + m_ZAdjustClick: 0.05 + m_HoverScale: 1.1 + m_HoverBoxColliderGrow: 0.2 + m_AddOverlay: 0 + m_Command: 0 + m_CommandParam: -1 + m_CommandParam2: -1 + m_RequiresPopup: 0 + m_CenterPopupOnButton: 0 + m_PopupOffset: {x: 0, y: 0, z: 0} + m_PopupText: + m_LocalizedPopup: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_ToggleOnDescription: + m_LocalizedToggleOnDescription: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_ToggleOnTexture: {fileID: 0} + m_AllowUnavailable: 0 + m_LinkedUIObject: {fileID: 0} + m_CommandIgnored: 0 + references: + version: 2 + RefIds: [] +--- !u!1 &3350558357556252257 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -4551,44 +4445,46 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 1583684570998085433} - - component: {fileID: 5194402002804098867} - - component: {fileID: 8290597564335685000} - - component: {fileID: 2511332541157942654} + - component: {fileID: 7580573523043848490} + - component: {fileID: 8140081930800988506} + - component: {fileID: 2514654466827372125} m_Layer: 16 - m_Name: Text + m_Name: Background m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!224 &1583684570998085433 -RectTransform: +--- !u!4 &7580573523043848490 +Transform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5315453881601467229} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: -0.009999992} - m_LocalScale: {x: 4, y: 4, z: 2.857143} + m_GameObject: {fileID: 3350558357556252257} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0.045} + m_LocalScale: {x: 2, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] - m_Father: {fileID: 7893921961113671483} - m_RootOrder: 0 + m_Father: {fileID: 181638217984195686} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0.5, y: 0.5} - m_AnchorMax: {x: 0.5, y: 0.5} - m_AnchoredPosition: {x: -0.20199999, y: 0} - m_SizeDelta: {x: 0.3, y: 0.15} - m_Pivot: {x: 0, y: 0.5} ---- !u!23 &5194402002804098867 +--- !u!33 &8140081930800988506 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3350558357556252257} + m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &2514654466827372125 MeshRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5315453881601467229} + m_GameObject: {fileID: 3350558357556252257} m_Enabled: 1 m_CastShadows: 0 m_ReceiveShadows: 0 @@ -4602,7 +4498,7 @@ MeshRenderer: m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} + - {fileID: 2100000, guid: 0ead8b8e224bcf040862605f5eed7211, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 @@ -4611,10 +4507,10 @@ MeshRenderer: m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 m_ReceiveGI: 1 - m_PreserveUVs: 0 + m_PreserveUVs: 1 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 - m_StitchLightmapSeams: 1 + m_StitchLightmapSeams: 0 m_SelectedEditorRenderState: 3 m_MinimumChartSize: 4 m_AutoUVMaxDistance: 0.5 @@ -4624,139 +4520,90 @@ MeshRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!114 &8290597564335685000 -MonoBehaviour: +--- !u!1 &3364245950019763117 +GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5315453881601467229} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 9541d86e2fd84c1d9990edf0852d74ab, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Material: {fileID: 0} - m_Color: {r: 1, g: 1, b: 1, a: 1} - m_RaycastTarget: 1 - m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} - m_Maskable: 1 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_text: SIGN IN - m_isRightToLeft: 0 - m_fontAsset: {fileID: 11400000, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} - m_sharedMaterial: {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} - m_fontSharedMaterials: [] - m_fontMaterial: {fileID: 0} - m_fontMaterials: [] - m_fontColor32: - serializedVersion: 2 - rgba: 4294967295 - m_fontColor: {r: 1, g: 1, b: 1, a: 1} - m_enableVertexGradient: 0 - m_colorMode: 3 - m_fontColorGradient: - topLeft: {r: 1, g: 1, b: 1, a: 1} - topRight: {r: 1, g: 1, b: 1, a: 1} - bottomLeft: {r: 1, g: 1, b: 1, a: 1} - bottomRight: {r: 1, g: 1, b: 1, a: 1} - m_fontColorGradientPreset: {fileID: 0} - m_spriteAsset: {fileID: 0} - m_tintAllSprites: 0 - m_StyleSheet: {fileID: 0} - m_TextStyleHashCode: -1183493901 - m_overrideHtmlColors: 0 - m_faceColor: - serializedVersion: 2 - rgba: 4294967295 - m_fontSize: 0.86 - m_fontSizeBase: 0.86 - m_fontWeight: 400 - m_enableAutoSizing: 0 - m_fontSizeMin: 18 - m_fontSizeMax: 72 - m_fontStyle: 0 - m_HorizontalAlignment: 1 - m_VerticalAlignment: 512 - m_textAlignment: 65535 - m_characterSpacing: 0 - m_wordSpacing: 0 - m_lineSpacing: 0 - m_lineSpacingMax: 0 - m_paragraphSpacing: 0 - m_charWidthMaxAdj: 0 - m_enableWordWrapping: 1 - m_wordWrappingRatios: 0.4 - m_overflowMode: 0 - m_linkedTextComponent: {fileID: 0} - parentLinkedComponent: {fileID: 0} - m_enableKerning: 1 - m_enableExtraPadding: 0 - checkPaddingRequired: 0 - m_isRichText: 1 - m_parseCtrlCharacters: 1 - m_isOrthographic: 0 - m_isCullingEnabled: 0 - m_horizontalMapping: 0 - m_verticalMapping: 0 - m_uvLineOffset: 0 - m_geometrySortingOrder: 0 - m_IsTextObjectScaleStatic: 0 - m_VertexBufferAutoSizeReduction: 0 - m_useMaxVisibleDescender: 1 - m_pageToDisplay: 1 - m_margin: {x: 0, y: 0, z: 0, w: 0} - m_isUsingLegacyAnimationComponent: 0 - m_isVolumetricText: 0 - _SortingLayer: 0 - _SortingLayerID: 0 - _SortingOrder: 0 - m_hasFontAssetChanged: 0 - m_renderer: {fileID: 5194402002804098867} - m_maskType: 0 ---- !u!114 &2511332541157942654 -MonoBehaviour: + serializedVersion: 6 + m_Component: + - component: {fileID: 5914045499585322770} + - component: {fileID: 7765932664411523162} + - component: {fileID: 1640930553324643105} + m_Layer: 16 + m_Name: Icosa_BackPlate + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &5914045499585322770 +Transform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5315453881601467229} + m_GameObject: {fileID: 3364245950019763117} + serializedVersion: 2 + m_LocalRotation: {x: -0.7071068, y: -0, z: -0, w: 0.7071067} + m_LocalPosition: {x: 0.621, y: -0.151, z: -0.005} + m_LocalScale: {x: 47, y: 49.999924, z: 74.2} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 8994260351568061772} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!33 &7765932664411523162 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3364245950019763117} + m_Mesh: {fileID: 4300002, guid: 3efe5b86b55995545a231ce66a53b402, type: 3} +--- !u!23 &1640930553324643105 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3364245950019763117} m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 69beb381e244f92449b8c4cf954630e9, type: 3} - m_Name: - m_EditorClassIdentifier: - m_TrackedObjects: - - rid: 3215294302546034846 - references: - version: 2 - RefIds: - - rid: 3215294302546034846 - type: {class: TrackedUGuiGraphic, ns: UnityEngine.Localization.PropertyVariants.TrackedObjects, - asm: Unity.Localization} - data: - m_Target: {fileID: 8290597564335685000} - m_TrackedProperties: - items: - - rid: 3215294302546034847 - m_UpdateType: 0 - - rid: 3215294302546034847 - type: {class: LocalizedStringProperty, ns: UnityEngine.Localization.PropertyVariants.TrackedProperties, - asm: Unity.Localization} - data: - m_Localized: - m_TableReference: - m_TableCollectionName: GUID:c84355079ab3f3e4f8f3812258805f86 - m_TableEntryReference: - m_KeyId: 7933561489039360 - m_Key: - m_FallbackState: 0 - m_WaitForCompletion: 0 - m_LocalVariables: [] - m_PropertyPath: m_text ---- !u!1 &5403683023149528791 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 8fe8230ee7ae32a4eb7fe6d5df34ebd4, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 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 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!1 &3364253099164516464 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -4764,58 +4611,60 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 4704522903857296483} - - component: {fileID: 6212349802531054436} - - component: {fileID: 8705749884328266341} - - component: {fileID: 832193050044176433} - m_Layer: 0 - m_Name: Description + - component: {fileID: 7380447630107943821} + - component: {fileID: 2437227728573446938} + - component: {fileID: 7038645423114811503} + m_Layer: 16 + m_Name: MeshBackground m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!224 &4704522903857296483 -RectTransform: +--- !u!4 &7380447630107943821 +Transform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5403683023149528791} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: -0.0025} - m_LocalScale: {x: 1, y: 1, z: 1} + m_GameObject: {fileID: 3364253099164516464} + serializedVersion: 2 + m_LocalRotation: {x: 0.7071068, y: -0, z: -0, w: 0.7071068} + m_LocalPosition: {x: 0, y: 0, z: 0.025} + m_LocalScale: {x: 0.79999995, y: 0.02, z: 0.8} m_ConstrainProportionsScale: 0 m_Children: [] - m_Father: {fileID: 3457603883277620212} - m_RootOrder: 1 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0.5, y: 0.5} - m_AnchorMax: {x: 0.5, y: 0.5} - m_AnchoredPosition: {x: 0, y: 0.058} - m_SizeDelta: {x: 2.5, y: 0.7} - m_Pivot: {x: 0.5, y: 0.5} ---- !u!23 &6212349802531054436 + m_Father: {fileID: 8121802616684643442} + m_LocalEulerAnglesHint: {x: 90, y: 0, z: 0} +--- !u!33 &2437227728573446938 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3364253099164516464} + m_Mesh: {fileID: 10206, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &7038645423114811503 MeshRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5403683023149528791} + m_GameObject: {fileID: 3364253099164516464} m_Enabled: 1 m_CastShadows: 0 m_ReceiveShadows: 0 m_DynamicOccludee: 1 m_StaticShadowCaster: 0 m_MotionVectors: 1 - m_LightProbeUsage: 0 + m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} + - {fileID: 2100000, guid: 77dd4ff8b1158a84397aba783cd0af05, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 @@ -4824,7 +4673,7 @@ MeshRenderer: m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 m_ReceiveGI: 1 - m_PreserveUVs: 0 + m_PreserveUVs: 1 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 m_StitchLightmapSeams: 0 @@ -4837,141 +4686,90 @@ MeshRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!114 &8705749884328266341 -MonoBehaviour: +--- !u!1 &3387414818891217864 +GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5403683023149528791} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 9541d86e2fd84c1d9990edf0852d74ab, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Material: {fileID: 0} - m_Color: {r: 1, g: 1, b: 1, a: 1} - m_RaycastTarget: 1 - m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} - m_Maskable: 1 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_text: 'Sign in to a Sketchfab account to allow - - uploading to Sketchfab.' - m_isRightToLeft: 0 - m_fontAsset: {fileID: 11400000, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} - m_sharedMaterial: {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} - m_fontSharedMaterials: [] - m_fontMaterial: {fileID: 0} - m_fontMaterials: [] - m_fontColor32: - serializedVersion: 2 - rgba: 4286085240 - m_fontColor: {r: 0.47058824, g: 0.47058824, b: 0.47058824, a: 1} - m_enableVertexGradient: 0 - m_colorMode: 3 - m_fontColorGradient: - topLeft: {r: 1, g: 1, b: 1, a: 1} - topRight: {r: 1, g: 1, b: 1, a: 1} - bottomLeft: {r: 1, g: 1, b: 1, a: 1} - bottomRight: {r: 1, g: 1, b: 1, a: 1} - m_fontColorGradientPreset: {fileID: 0} - m_spriteAsset: {fileID: 0} - m_tintAllSprites: 0 - m_StyleSheet: {fileID: 0} - m_TextStyleHashCode: -1183493901 - m_overrideHtmlColors: 0 - m_faceColor: - serializedVersion: 2 - rgba: 4294967295 - m_fontSize: 1.275 - m_fontSizeBase: 1.275 - m_fontWeight: 400 - m_enableAutoSizing: 0 - m_fontSizeMin: 18 - m_fontSizeMax: 72 - m_fontStyle: 0 - m_HorizontalAlignment: 2 - m_VerticalAlignment: 512 - m_textAlignment: 65535 - m_characterSpacing: 0 - m_wordSpacing: 0 - m_lineSpacing: 0 - m_lineSpacingMax: 0 - m_paragraphSpacing: 0 - m_charWidthMaxAdj: 0 - m_enableWordWrapping: 1 - m_wordWrappingRatios: 0.4 - m_overflowMode: 0 - m_linkedTextComponent: {fileID: 0} - parentLinkedComponent: {fileID: 0} - m_enableKerning: 1 - m_enableExtraPadding: 0 - checkPaddingRequired: 0 - m_isRichText: 1 - m_parseCtrlCharacters: 1 - m_isOrthographic: 0 - m_isCullingEnabled: 0 - m_horizontalMapping: 0 - m_verticalMapping: 0 - m_uvLineOffset: 0 - m_geometrySortingOrder: 0 - m_IsTextObjectScaleStatic: 0 - m_VertexBufferAutoSizeReduction: 0 - m_useMaxVisibleDescender: 1 - m_pageToDisplay: 1 - m_margin: {x: 0, y: 0, z: 0, w: 0} - m_isUsingLegacyAnimationComponent: 0 - m_isVolumetricText: 0 - _SortingLayer: 0 - _SortingLayerID: 0 - _SortingOrder: 0 - m_hasFontAssetChanged: 0 - m_renderer: {fileID: 6212349802531054436} - m_maskType: 0 ---- !u!114 &832193050044176433 -MonoBehaviour: + serializedVersion: 6 + m_Component: + - component: {fileID: 4946117081540083272} + - component: {fileID: 1555734638323418344} + - component: {fileID: 6328234730399420729} + m_Layer: 16 + m_Name: Sketchfab_Logo + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4946117081540083272 +Transform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5403683023149528791} + m_GameObject: {fileID: 3387414818891217864} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0.278, y: 0.26200008, z: -0.01} + m_LocalScale: {x: 0.2649999, y: 0.2649999, z: 0.2649999} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 534589999851858800} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!33 &1555734638323418344 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3387414818891217864} + m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &6328234730399420729 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3387414818891217864} m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 69beb381e244f92449b8c4cf954630e9, type: 3} - m_Name: - m_EditorClassIdentifier: - m_TrackedObjects: - - rid: 3215294302546034856 - references: - version: 2 - RefIds: - - rid: 3215294302546034856 - type: {class: TrackedUGuiGraphic, ns: UnityEngine.Localization.PropertyVariants.TrackedObjects, - asm: Unity.Localization} - data: - m_Target: {fileID: 8705749884328266341} - m_TrackedProperties: - items: - - rid: 3215294302546034857 - m_UpdateType: 0 - - rid: 3215294302546034857 - type: {class: LocalizedStringProperty, ns: UnityEngine.Localization.PropertyVariants.TrackedProperties, - asm: Unity.Localization} - data: - m_Localized: - m_TableReference: - m_TableCollectionName: GUID:c84355079ab3f3e4f8f3812258805f86 - m_TableEntryReference: - m_KeyId: 76138521224077312 - m_Key: - m_FallbackState: 0 - m_WaitForCompletion: 0 - m_LocalVariables: [] - m_PropertyPath: m_text ---- !u!1 &5419396676487616149 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 0 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 46140578835b4f14582726c5d76a6eda, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 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 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!1 &3674036727267325941 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -4979,55 +4777,57 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 5446221535905318599} - - component: {fileID: 5255334288434809734} - - component: {fileID: 1369930125958929065} - - component: {fileID: 4730200966117401982} - - component: {fileID: 712852433553107461} + - component: {fileID: 5521146392998997215} + - component: {fileID: 3994049754972082256} + - component: {fileID: 619260971007631306} + - component: {fileID: 2495991278148453507} + - component: {fileID: 4355862344388155723} m_Layer: 16 - m_Name: Google_SignOut + m_Name: Button_ClosePopup m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!4 &5446221535905318599 +--- !u!4 &5521146392998997215 Transform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5419396676487616149} + m_GameObject: {fileID: 3674036727267325941} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: -0.398, y: -0.242, z: -0.06} - m_LocalScale: {x: 0.35, y: 0.35, z: 0.35} + m_LocalPosition: {x: 1.251, y: -0.75199986, z: -0.018} + m_LocalScale: {x: 0.29999998, y: 0.29999998, z: 0.29999998} m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 7741920746089690377} - m_RootOrder: 2 + m_Children: + - {fileID: 6855474239171570967} + - {fileID: 4100876239645834569} + m_Father: {fileID: 3576301794080265196} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!33 &5255334288434809734 +--- !u!33 &3994049754972082256 MeshFilter: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5419396676487616149} + m_GameObject: {fileID: 3674036727267325941} m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} ---- !u!23 &1369930125958929065 +--- !u!23 &619260971007631306 MeshRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5419396676487616149} - m_Enabled: 1 + m_GameObject: {fileID: 3674036727267325941} + m_Enabled: 0 m_CastShadows: 0 m_ReceiveShadows: 0 m_DynamicOccludee: 1 m_StaticShadowCaster: 0 m_MotionVectors: 1 - m_LightProbeUsage: 1 + m_LightProbeUsage: 0 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 m_RayTraceProcedural: 0 @@ -5043,7 +4843,7 @@ MeshRenderer: m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 m_ReceiveGI: 1 - m_PreserveUVs: 1 + m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 m_StitchLightmapSeams: 0 @@ -5056,26 +4856,47 @@ MeshRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!114 &4730200966117401982 +--- !u!65 &2495991278148453507 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3674036727267325941} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Size: {x: 1.0000001, y: 1, z: 0.01} + m_Center: {x: 0, y: 0, z: -0.01} +--- !u!114 &4355862344388155723 MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5419396676487616149} + m_GameObject: {fileID: 3674036727267325941} m_Enabled: 1 m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 6c6859eec74651247968d56b594ac313, type: 3} + m_Script: {fileID: 11500000, guid: fc12adcafa62a22458e635d2ee7e78b5, type: 3} m_Name: m_EditorClassIdentifier: m_DescriptionType: 0 m_DescriptionYOffset: 0 - m_DescriptionText: POPUP_ACCOUNTS_SIGNOUT_BUTTON_DESCRIPTION + m_DescriptionText: Close m_LocalizedDescription: m_TableReference: - m_TableCollectionName: GUID:c84355079ab3f3e4f8f3812258805f86 + m_TableCollectionName: m_TableEntryReference: - m_KeyId: 15522362785837056 + m_KeyId: 0 m_Key: m_FallbackState: 0 m_WaitForCompletion: 0 @@ -5092,18 +4913,18 @@ MonoBehaviour: m_LocalVariables: [] m_DescriptionActivateSpeed: 12 m_DescriptionZScale: 1 - m_ButtonTexture: {fileID: 2800000, guid: 6bd8742b210a6444e85b5c86f80ffebc, type: 3} - m_AtlasTexture: 1 + m_ButtonTexture: {fileID: 0} + m_AtlasTexture: 0 m_ToggleButton: 0 m_LongPressReleaseButton: 0 m_ButtonHasPressedAudio: 1 m_ZAdjustHover: -0.02 - m_ZAdjustClick: 0.05 + m_ZAdjustClick: 0.03 m_HoverScale: 1.1 m_HoverBoxColliderGrow: 0.2 m_AddOverlay: 0 - m_Command: 27 - m_CommandParam: 1 + m_Command: 0 + m_CommandParam: -1 m_CommandParam2: -1 m_RequiresPopup: 0 m_CenterPopupOnButton: 0 @@ -5131,88 +4952,72 @@ MonoBehaviour: m_ToggleOnTexture: {fileID: 0} m_AllowUnavailable: 0 m_LinkedUIObject: {fileID: 0} + m_CommandIgnored: 0 references: version: 2 RefIds: [] ---- !u!65 &712852433553107461 -BoxCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5419396676487616149} - m_Material: {fileID: 0} - m_IsTrigger: 0 - m_Enabled: 1 - serializedVersion: 2 - m_Size: {x: 1, y: 1.0000001, z: 0.1} - m_Center: {x: 0, y: 0, z: -0.01} ---- !u!1 &5427861527217224720 -GameObject: +--- !u!1 &3793285321450572269 +GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 6721629502030059466} - - component: {fileID: 744816621245303203} - - component: {fileID: 5315415322598248231} - - component: {fileID: 7149889851386687525} - - component: {fileID: 5696691115232969362} - m_Layer: 14 - m_Name: ConfirmationButton + - component: {fileID: 6855474239171570967} + - component: {fileID: 4593108259088090395} + - component: {fileID: 1617028310973550690} + m_Layer: 16 + m_Name: Mesh m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!4 &6721629502030059466 +--- !u!4 &6855474239171570967 Transform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5427861527217224720} + m_GameObject: {fileID: 3793285321450572269} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: -0.434, z: -0.08} - m_LocalScale: {x: 0.6, y: 0.29999998, z: 0.29999998} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 0.65, y: 0.65, z: 1} m_ConstrainProportionsScale: 0 - m_Children: - - {fileID: 3215585481372348197} - - {fileID: 5384230387207399056} - m_Father: {fileID: 4825048073929942150} - m_RootOrder: 2 + m_Children: [] + m_Father: {fileID: 5521146392998997215} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!33 &744816621245303203 +--- !u!33 &4593108259088090395 MeshFilter: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5427861527217224720} + m_GameObject: {fileID: 3793285321450572269} m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} ---- !u!23 &5315415322598248231 +--- !u!23 &1617028310973550690 MeshRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5427861527217224720} - m_Enabled: 0 + m_GameObject: {fileID: 3793285321450572269} + m_Enabled: 1 m_CastShadows: 0 m_ReceiveShadows: 0 m_DynamicOccludee: 1 m_StaticShadowCaster: 0 m_MotionVectors: 1 - m_LightProbeUsage: 0 + m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 2100000, guid: 3c8ca511828182747a0b79564892ec57, type: 2} + - {fileID: 2100000, guid: 0d7eb02b18ffb4c419fb75924cb900dc, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 @@ -5221,7 +5026,7 @@ MeshRenderer: m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 m_ReceiveGI: 1 - m_PreserveUVs: 0 + m_PreserveUVs: 1 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 m_StitchLightmapSeams: 0 @@ -5234,99 +5039,90 @@ MeshRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!65 &7149889851386687525 -BoxCollider: +--- !u!1 &3883720175326442003 +GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5427861527217224720} - m_Material: {fileID: 0} - m_IsTrigger: 0 - m_Enabled: 1 + serializedVersion: 6 + m_Component: + - component: {fileID: 6692607038900794975} + - component: {fileID: 1080627186782362197} + - component: {fileID: 2964682892386166551} + m_Layer: 16 + m_Name: Google_BackPlate + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &6692607038900794975 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3883720175326442003} serializedVersion: 2 - m_Size: {x: 1, y: 1, z: 0.01} - m_Center: {x: 0, y: 0, z: -0.01} ---- !u!114 &5696691115232969362 -MonoBehaviour: + m_LocalRotation: {x: -0.7071068, y: -0, z: -0, w: 0.7071067} + m_LocalPosition: {x: -0.621, y: -0.151, z: -0.005} + m_LocalScale: {x: 47, y: 49.999924, z: 74.2} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1411852402157678472} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!33 &1080627186782362197 +MeshFilter: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5427861527217224720} + m_GameObject: {fileID: 3883720175326442003} + m_Mesh: {fileID: 4300002, guid: 3efe5b86b55995545a231ce66a53b402, type: 3} +--- !u!23 &2964682892386166551 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3883720175326442003} m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fc12adcafa62a22458e635d2ee7e78b5, type: 3} - m_Name: - m_EditorClassIdentifier: - m_DescriptionType: -1 - m_DescriptionYOffset: 0 - m_DescriptionText: - m_LocalizedDescription: - m_TableReference: - m_TableCollectionName: - m_TableEntryReference: - m_KeyId: 0 - m_Key: - m_FallbackState: 0 - m_WaitForCompletion: 0 - m_LocalVariables: [] - m_DescriptionTextExtra: - m_LocalizedDescriptionExtra: - m_TableReference: - m_TableCollectionName: - m_TableEntryReference: - m_KeyId: 0 - m_Key: - m_FallbackState: 0 - m_WaitForCompletion: 0 - m_LocalVariables: [] - m_DescriptionActivateSpeed: 12 - m_DescriptionZScale: 1 - m_ButtonTexture: {fileID: 0} - m_AtlasTexture: 0 - m_ToggleButton: 0 - m_LongPressReleaseButton: 0 - m_ButtonHasPressedAudio: 1 - m_ZAdjustHover: -0.02 - m_ZAdjustClick: 0.05 - m_HoverScale: 1.1 - m_HoverBoxColliderGrow: 0.2 - m_AddOverlay: 0 - m_Command: 0 - m_CommandParam: -1 - m_CommandParam2: -1 - m_RequiresPopup: 0 - m_CenterPopupOnButton: 0 - m_PopupOffset: {x: 0, y: 0, z: 0} - m_PopupText: - m_LocalizedPopup: - m_TableReference: - m_TableCollectionName: - m_TableEntryReference: - m_KeyId: 0 - m_Key: - m_FallbackState: 0 - m_WaitForCompletion: 0 - m_LocalVariables: [] - m_ToggleOnDescription: - m_LocalizedToggleOnDescription: - m_TableReference: - m_TableCollectionName: - m_TableEntryReference: - m_KeyId: 0 - m_Key: - m_FallbackState: 0 - m_WaitForCompletion: 0 - m_LocalVariables: [] - m_ToggleOnTexture: {fileID: 0} - m_AllowUnavailable: 0 - m_LinkedUIObject: {fileID: 0} - m_CommandIgnored: 0 - references: - version: 2 - RefIds: [] ---- !u!1 &5649685825589421528 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 8fe8230ee7ae32a4eb7fe6d5df34ebd4, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 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 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!1 &3893413551512185020 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -5334,34 +5130,35 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 6423827612944397798} + - component: {fileID: 1000721931266647293} m_Layer: 16 - m_Name: Sketchfab_ConfirmSignOutElements + m_Name: Icosa_SignedOutElements m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!4 &6423827612944397798 +--- !u!4 &1000721931266647293 Transform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5649685825589421528} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_GameObject: {fileID: 3893413551512185020} + serializedVersion: 2 + 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_ConstrainProportionsScale: 0 m_Children: - - {fileID: 8245513620673000221} - - {fileID: 4111961635044152573} - - {fileID: 6124434747938532598} - - {fileID: 4120900520909079457} - m_Father: {fileID: 149137880941958609} - m_RootOrder: 2 + - {fileID: 3326273886487770573} + - {fileID: 5038995524656264454} + - {fileID: 96286366463442578} + - {fileID: 2403478784508930027} + - {fileID: 5520953697447238279} + m_Father: {fileID: 7706333168622570552} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &5866976969575595662 +--- !u!1 &4082436277880791083 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -5369,34 +5166,33 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 529827201699571093} + - component: {fileID: 5854179938074699431} m_Layer: 16 - m_Name: Sketchfab_SignedInElements + m_Name: Google m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!4 &529827201699571093 +--- !u!4 &5854179938074699431 Transform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5866976969575595662} + m_GameObject: {fileID: 4082436277880791083} + serializedVersion: 2 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_ConstrainProportionsScale: 0 m_Children: - - {fileID: 7314565180282189882} - - {fileID: 5621771514230647440} - - {fileID: 90735575297890764} - - {fileID: 5753424830644711893} - m_Father: {fileID: 149137880941958609} - m_RootOrder: 0 + - {fileID: 1411852402157678472} + - {fileID: 1432546188030660464} + - {fileID: 7741920746089690377} + m_Father: {fileID: 8645625735416266758} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &5921053250823053932 +--- !u!1 &4103205528941609404 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -5404,46 +5200,48 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 798000693479046927} - - component: {fileID: 1551091070195428418} - - component: {fileID: 3372310621534254453} + - component: {fileID: 4700142148089133932} + - component: {fileID: 3380311651882997193} + - component: {fileID: 4297529096568456498} + - component: {fileID: 5219542430503434550} + - component: {fileID: 586799646275115208} m_Layer: 16 - m_Name: IconEnabled + m_Name: Sketchfab_Info m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!4 &798000693479046927 +--- !u!4 &4700142148089133932 Transform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5921053250823053932} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: -0.33714277, y: -0.011110305, z: -0.024999999} - m_LocalScale: {x: 0.21428569, y: 0.8333332, z: 0.15} + m_GameObject: {fileID: 4103205528941609404} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 1.046, y: 0.2620001, z: -0.025} + m_LocalScale: {x: 0.2, y: 0.2, z: 0.2} m_ConstrainProportionsScale: 0 m_Children: [] - m_Father: {fileID: 1741904442304953456} - m_RootOrder: 0 + m_Father: {fileID: 534589999851858800} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!33 &1551091070195428418 +--- !u!33 &3380311651882997193 MeshFilter: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5921053250823053932} + m_GameObject: {fileID: 4103205528941609404} m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} ---- !u!23 &3372310621534254453 +--- !u!23 &4297529096568456498 MeshRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 5921053250823053932} + m_GameObject: {fileID: 4103205528941609404} m_Enabled: 1 m_CastShadows: 0 m_ReceiveShadows: 0 @@ -5457,7 +5255,7 @@ MeshRenderer: m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 2100000, guid: 3f00bfbfa437f004888833cf848a2416, type: 2} + - {fileID: 2100000, guid: 3c8ca511828182747a0b79564892ec57, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 @@ -5479,7 +5277,107 @@ MeshRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!1 &6559160341867036930 +--- !u!114 &5219542430503434550 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4103205528941609404} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fc12adcafa62a22458e635d2ee7e78b5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_DescriptionType: -1 + m_DescriptionYOffset: 0 + m_DescriptionText: + m_LocalizedDescription: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_DescriptionTextExtra: + m_LocalizedDescriptionExtra: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_DescriptionActivateSpeed: 12 + m_DescriptionZScale: 1 + m_ButtonTexture: {fileID: 2800000, guid: bb4439b4279219b4db937c93530893ff, type: 3} + m_AtlasTexture: 1 + m_ToggleButton: 0 + m_LongPressReleaseButton: 0 + m_ButtonHasPressedAudio: 1 + m_ZAdjustHover: -0.02 + m_ZAdjustClick: 0.05 + m_HoverScale: 1.2 + m_HoverBoxColliderGrow: 0.2 + m_AddOverlay: 0 + m_Command: 73 + m_CommandParam: 2 + m_CommandParam2: -1 + m_RequiresPopup: 0 + m_CenterPopupOnButton: 0 + m_PopupOffset: {x: 0, y: 0, z: 0} + m_PopupText: + m_LocalizedPopup: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_ToggleOnDescription: + m_LocalizedToggleOnDescription: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_ToggleOnTexture: {fileID: 0} + m_AllowUnavailable: 0 + m_LinkedUIObject: {fileID: 0} + m_CommandIgnored: 0 + references: + version: 2 + RefIds: [] +--- !u!65 &586799646275115208 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4103205528941609404} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Size: {x: 1, y: 1.0000001, z: 0.1} + m_Center: {x: 0, y: 0, z: -0.01} +--- !u!1 &4105427794534146856 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -5487,58 +5385,62 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 8844894437526037228} - - component: {fileID: 2123032824923807014} - - component: {fileID: 2425192678641992511} - - component: {fileID: 439132055978833134} - m_Layer: 0 - m_Name: Description + - component: {fileID: 4120900520909079457} + - component: {fileID: 4957999687296029088} + - component: {fileID: 6324396148345559707} + - component: {fileID: 5104710591034478679} + - component: {fileID: 7087448018191981113} + m_Layer: 16 + m_Name: Sketchfab_Cancel m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!224 &8844894437526037228 -RectTransform: +--- !u!4 &4120900520909079457 +Transform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6559160341867036930} + m_GameObject: {fileID: 4105427794534146856} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: -0.0025} - m_LocalScale: {x: 1, y: 1, z: 1} + m_LocalPosition: {x: 0.398, y: -0.242, z: -0.06} + m_LocalScale: {x: 0.35, y: 0.35, z: 0.35} m_ConstrainProportionsScale: 0 m_Children: [] - m_Father: {fileID: 4825048073929942150} - m_RootOrder: 1 + m_Father: {fileID: 6423827612944397798} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0.5, y: 0.5} - m_AnchorMax: {x: 0.5, y: 0.5} - m_AnchoredPosition: {x: 0, y: 0.058} - m_SizeDelta: {x: 2.5, y: 0.7} - m_Pivot: {x: 0.5, y: 0.5} ---- !u!23 &2123032824923807014 +--- !u!33 &4957999687296029088 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4105427794534146856} + m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &6324396148345559707 MeshRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6559160341867036930} + m_GameObject: {fileID: 4105427794534146856} m_Enabled: 1 m_CastShadows: 0 m_ReceiveShadows: 0 m_DynamicOccludee: 1 m_StaticShadowCaster: 0 m_MotionVectors: 1 - m_LightProbeUsage: 0 + m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} + - {fileID: 2100000, guid: 40d29de2bdc11f04dbfa25059165916e, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 @@ -5547,7 +5449,7 @@ MeshRenderer: m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 m_ReceiveGI: 1 - m_PreserveUVs: 0 + m_PreserveUVs: 1 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 m_StitchLightmapSeams: 0 @@ -5560,39 +5462,217 @@ MeshRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!114 &2425192678641992511 +--- !u!114 &5104710591034478679 MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6559160341867036930} + m_GameObject: {fileID: 4105427794534146856} m_Enabled: 1 m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 9541d86e2fd84c1d9990edf0852d74ab, type: 3} + m_Script: {fileID: 11500000, guid: fc12adcafa62a22458e635d2ee7e78b5, type: 3} m_Name: m_EditorClassIdentifier: + m_DescriptionType: 0 + m_DescriptionYOffset: 0 + m_DescriptionText: Cancel + m_LocalizedDescription: + m_TableReference: + m_TableCollectionName: GUID:c84355079ab3f3e4f8f3812258805f86 + m_TableEntryReference: + m_KeyId: 15526523405381632 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_DescriptionTextExtra: + m_LocalizedDescriptionExtra: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_DescriptionActivateSpeed: 12 + m_DescriptionZScale: 1 + m_ButtonTexture: {fileID: 2800000, guid: 957f69e59565cd1469fa095b415fa513, type: 3} + m_AtlasTexture: 0 + m_ToggleButton: 0 + m_LongPressReleaseButton: 0 + m_ButtonHasPressedAudio: 1 + m_ZAdjustHover: -0.02 + m_ZAdjustClick: 0.05 + m_HoverScale: 1.1 + m_HoverBoxColliderGrow: 0.2 + m_AddOverlay: 0 + m_Command: 0 + m_CommandParam: 2 + m_CommandParam2: -1 + m_RequiresPopup: 0 + m_CenterPopupOnButton: 0 + m_PopupOffset: {x: 0, y: 0, z: 0} + m_PopupText: + m_LocalizedPopup: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_ToggleOnDescription: + m_LocalizedToggleOnDescription: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_ToggleOnTexture: {fileID: 0} + m_AllowUnavailable: 0 + m_LinkedUIObject: {fileID: 0} + m_CommandIgnored: 1 + references: + version: 2 + RefIds: [] +--- !u!65 &7087448018191981113 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4105427794534146856} m_Material: {fileID: 0} - m_Color: {r: 1, g: 1, b: 1, a: 1} - m_RaycastTarget: 1 - m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} - m_Maskable: 1 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_text: 'Sign in to a Google account to access - - Drive and YouTube support.' - m_isRightToLeft: 0 - m_fontAsset: {fileID: 11400000, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} - m_sharedMaterial: {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Size: {x: 1, y: 1.0000001, z: 0.1} + m_Center: {x: 0, y: 0, z: -0.01} +--- !u!1 &4148507089762079577 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2729332839612941327} + - component: {fileID: 6945091220654625637} + - component: {fileID: 198924042195436663} + - component: {fileID: 2813503354310912859} + m_Layer: 16 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &2729332839612941327 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4148507089762079577} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: -0.009999992} + m_LocalScale: {x: 4, y: 4, z: 2.857143} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 5520953697447238279} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: -0.202, y: 0} + m_SizeDelta: {x: 0.3, y: 0.15} + m_Pivot: {x: 0, y: 0.5} +--- !u!23 &6945091220654625637 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4148507089762079577} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + 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 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!114 &198924042195436663 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4148507089762079577} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 9541d86e2fd84c1d9990edf0852d74ab, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_text: SIGN IN + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} + m_sharedMaterial: {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} m_fontSharedMaterials: [] m_fontMaterial: {fileID: 0} m_fontMaterials: [] m_fontColor32: serializedVersion: 2 - rgba: 4286085240 - m_fontColor: {r: 0.47058824, g: 0.47058824, b: 0.47058824, a: 1} + rgba: 4294967295 + m_fontColor: {r: 1, g: 1, b: 1, a: 1} m_enableVertexGradient: 0 m_colorMode: 3 m_fontColorGradient: @@ -5609,14 +5689,14 @@ MonoBehaviour: m_faceColor: serializedVersion: 2 rgba: 4294967295 - m_fontSize: 1.275 - m_fontSizeBase: 1.275 + m_fontSize: 0.86 + m_fontSizeBase: 0.86 m_fontWeight: 400 m_enableAutoSizing: 0 m_fontSizeMin: 18 m_fontSizeMax: 72 m_fontStyle: 0 - m_HorizontalAlignment: 2 + m_HorizontalAlignment: 1 m_VerticalAlignment: 512 m_textAlignment: 65535 m_characterSpacing: 0 @@ -5652,35 +5732,35 @@ MonoBehaviour: _SortingLayerID: 0 _SortingOrder: 0 m_hasFontAssetChanged: 0 - m_renderer: {fileID: 2123032824923807014} + m_renderer: {fileID: 6945091220654625637} m_maskType: 0 ---- !u!114 &439132055978833134 +--- !u!114 &2813503354310912859 MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6559160341867036930} + m_GameObject: {fileID: 4148507089762079577} m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 69beb381e244f92449b8c4cf954630e9, type: 3} m_Name: m_EditorClassIdentifier: m_TrackedObjects: - - rid: 3215294302546034852 + - rid: 3215294302546034848 references: version: 2 RefIds: - - rid: 3215294302546034852 + - rid: 3215294302546034848 type: {class: TrackedUGuiGraphic, ns: UnityEngine.Localization.PropertyVariants.TrackedObjects, asm: Unity.Localization} data: - m_Target: {fileID: 2425192678641992511} + m_Target: {fileID: 198924042195436663} m_TrackedProperties: items: - - rid: 3215294302546034853 + - rid: 3215294302546034849 m_UpdateType: 0 - - rid: 3215294302546034853 + - rid: 3215294302546034849 type: {class: LocalizedStringProperty, ns: UnityEngine.Localization.PropertyVariants.TrackedProperties, asm: Unity.Localization} data: @@ -5688,13 +5768,13 @@ MonoBehaviour: m_TableReference: m_TableCollectionName: GUID:c84355079ab3f3e4f8f3812258805f86 m_TableEntryReference: - m_KeyId: 76138083292602368 + m_KeyId: 7933561489039360 m_Key: m_FallbackState: 0 m_WaitForCompletion: 0 m_LocalVariables: [] m_PropertyPath: m_text ---- !u!1 &6569154546886767970 +--- !u!1 &4316944982740412120 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -5702,48 +5782,46 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 6952797202003472198} - - component: {fileID: 3857003002993330428} - - component: {fileID: 5268851330295692068} - - component: {fileID: 4382059402420719972} - - component: {fileID: 3651181850301530278} + - component: {fileID: 1180802039870758397} + - component: {fileID: 390951240049198343} + - component: {fileID: 6026671568046064672} m_Layer: 16 - m_Name: Google_Info + m_Name: IconDisabled m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!4 &6952797202003472198 +--- !u!4 &1180802039870758397 Transform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6569154546886767970} + m_GameObject: {fileID: 4316944982740412120} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: -0.213, y: 0.2620001, z: -0.025} - m_LocalScale: {x: 0.2, y: 0.2, z: 0.2} + m_LocalPosition: {x: -0.33714277, y: -0.011110305, z: -0.024999999} + m_LocalScale: {x: 0.21428569, y: 0.8333332, z: 0.15} m_ConstrainProportionsScale: 0 m_Children: [] - m_Father: {fileID: 1432546188030660464} - m_RootOrder: 3 + m_Father: {fileID: 1741904442304953456} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!33 &3857003002993330428 +--- !u!33 &390951240049198343 MeshFilter: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6569154546886767970} + m_GameObject: {fileID: 4316944982740412120} m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} ---- !u!23 &5268851330295692068 +--- !u!23 &6026671568046064672 MeshRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6569154546886767970} + m_GameObject: {fileID: 4316944982740412120} m_Enabled: 1 m_CastShadows: 0 m_ReceiveShadows: 0 @@ -5757,7 +5835,7 @@ MeshRenderer: m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 2100000, guid: 3c8ca511828182747a0b79564892ec57, type: 2} + - {fileID: 2100000, guid: 6b65e04b1b7fb5644862eb36bfcfb419, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 @@ -5779,26 +5857,111 @@ MeshRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!114 &4382059402420719972 +--- !u!1 &4516902404884197280 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1153672243062602464} + - component: {fileID: 3316034999128707532} + - component: {fileID: 4361165343961033676} + - component: {fileID: 1469645492926563259} + - component: {fileID: 2086513809805596120} + m_Layer: 16 + m_Name: Icosa_Cancel + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1153672243062602464 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4516902404884197280} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0.398, y: -0.242, z: -0.06} + m_LocalScale: {x: 0.35, y: 0.35, z: 0.35} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1675920430848132177} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!33 &3316034999128707532 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4516902404884197280} + m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &4361165343961033676 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4516902404884197280} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 40d29de2bdc11f04dbfa25059165916e, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 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 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!114 &1469645492926563259 MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6569154546886767970} + m_GameObject: {fileID: 4516902404884197280} m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: fc12adcafa62a22458e635d2ee7e78b5, type: 3} m_Name: m_EditorClassIdentifier: - m_DescriptionType: -1 + m_DescriptionType: 0 m_DescriptionYOffset: 0 - m_DescriptionText: + m_DescriptionText: Cancel m_LocalizedDescription: m_TableReference: - m_TableCollectionName: + m_TableCollectionName: GUID:c84355079ab3f3e4f8f3812258805f86 m_TableEntryReference: - m_KeyId: 0 + m_KeyId: 15526523405381632 m_Key: m_FallbackState: 0 m_WaitForCompletion: 0 @@ -5815,18 +5978,18 @@ MonoBehaviour: m_LocalVariables: [] m_DescriptionActivateSpeed: 12 m_DescriptionZScale: 1 - m_ButtonTexture: {fileID: 2800000, guid: bb4439b4279219b4db937c93530893ff, type: 3} - m_AtlasTexture: 1 + m_ButtonTexture: {fileID: 2800000, guid: 957f69e59565cd1469fa095b415fa513, type: 3} + m_AtlasTexture: 0 m_ToggleButton: 0 m_LongPressReleaseButton: 0 m_ButtonHasPressedAudio: 1 m_ZAdjustHover: -0.02 m_ZAdjustClick: 0.05 - m_HoverScale: 1.2 + m_HoverScale: 1.1 m_HoverBoxColliderGrow: 0.2 m_AddOverlay: 0 - m_Command: 73 - m_CommandParam: 1 + m_Command: 0 + m_CommandParam: 2 m_CommandParam2: -1 m_RequiresPopup: 0 m_CenterPopupOnButton: 0 @@ -5854,24 +6017,32 @@ MonoBehaviour: m_ToggleOnTexture: {fileID: 0} m_AllowUnavailable: 0 m_LinkedUIObject: {fileID: 0} - m_CommandIgnored: 0 + m_CommandIgnored: 1 references: version: 2 RefIds: [] ---- !u!65 &3651181850301530278 +--- !u!65 &2086513809805596120 BoxCollider: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6569154546886767970} + m_GameObject: {fileID: 4516902404884197280} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 + serializedVersion: 3 m_Size: {x: 1, y: 1.0000001, z: 0.1} m_Center: {x: 0, y: 0, z: -0.01} ---- !u!1 &6655431747887542890 +--- !u!1 &4539008613640430378 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -5879,43 +6050,161 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 277837882360728660} - - component: {fileID: 3967617528463584047} - - component: {fileID: 3967593321760830211} + - component: {fileID: 6661346418304443125} + - component: {fileID: 8976936997367820456} + - component: {fileID: 8201886566812613733} m_Layer: 16 - m_Name: Google_Text + m_Name: Sketchfab_Logo m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!224 &277837882360728660 -RectTransform: +--- !u!4 &6661346418304443125 +Transform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6655431747887542890} + m_GameObject: {fileID: 4539008613640430378} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: -0.01} + m_LocalPosition: {x: 0.37, y: -0.324, z: -0.025} + m_LocalScale: {x: 0.4, y: 0.4, z: 0.4} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 5621771514230647440} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!33 &8976936997367820456 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4539008613640430378} + m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &8201886566812613733 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4539008613640430378} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 0 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 46140578835b4f14582726c5d76a6eda, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 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 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!1 &4671315024118560739 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 7706333168622570552} + m_Layer: 16 + m_Name: Icosa + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &7706333168622570552 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4671315024118560739} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: -0.5611764, y: -1.1, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 8994260351568061772} + - {fileID: 1000721931266647293} + - {fileID: 1675920430848132177} + - {fileID: 282387885870267606} + m_Father: {fileID: 8645625735416266758} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &4884541372955623633 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 7758143906596955047} + - component: {fileID: 3414497333256173795} + - component: {fileID: 7198143098074655042} + - component: {fileID: 1849472563075584265} + m_Layer: 16 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &7758143906596955047 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4884541372955623633} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: -0.023000002} + m_LocalScale: {x: 1.7142857, y: 6.6666627, z: 0.8571429} + m_ConstrainProportionsScale: 0 m_Children: [] - m_Father: {fileID: 1432546188030660464} - m_RootOrder: 2 + m_Father: {fileID: 1741904442304953456} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} - m_AnchoredPosition: {x: -0.8228, y: 0.3524501} - m_SizeDelta: {x: 0.34, y: 0.17} - m_Pivot: {x: 0, y: 1} ---- !u!23 &3967617528463584047 + m_AnchoredPosition: {x: -0.183, y: -0.019} + m_SizeDelta: {x: 0.4, y: 0.1} + m_Pivot: {x: 0, y: 0.5} +--- !u!23 &3414497333256173795 MeshRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6655431747887542890} + m_GameObject: {fileID: 4884541372955623633} m_Enabled: 1 m_CastShadows: 0 m_ReceiveShadows: 0 @@ -5951,13 +6240,13 @@ MeshRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!114 &3967593321760830211 +--- !u!114 &7198143098074655042 MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6655431747887542890} + m_GameObject: {fileID: 4884541372955623633} m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 9541d86e2fd84c1d9990edf0852d74ab, type: 3} @@ -5971,7 +6260,7 @@ MonoBehaviour: m_OnCullStateChanged: m_PersistentCalls: m_Calls: [] - m_text: Google + m_text: Drive Backup m_isRightToLeft: 0 m_fontAsset: {fileID: 11400000, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} m_sharedMaterial: {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} @@ -5998,15 +6287,15 @@ MonoBehaviour: m_faceColor: serializedVersion: 2 rgba: 4294967295 - m_fontSize: 1.35 - m_fontSizeBase: 1.35 + m_fontSize: 0.785 + m_fontSizeBase: 0.785 m_fontWeight: 400 m_enableAutoSizing: 0 m_fontSizeMin: 18 m_fontSizeMax: 72 m_fontStyle: 0 m_HorizontalAlignment: 1 - m_VerticalAlignment: 256 + m_VerticalAlignment: 512 m_textAlignment: 65535 m_characterSpacing: 0 m_wordSpacing: 0 @@ -6041,9 +6330,49 @@ MonoBehaviour: _SortingLayerID: 0 _SortingOrder: 0 m_hasFontAssetChanged: 0 - m_renderer: {fileID: 3967617528463584047} + m_renderer: {fileID: 3414497333256173795} m_maskType: 0 ---- !u!1 &6877995767082855847 +--- !u!114 &1849472563075584265 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4884541372955623633} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 69beb381e244f92449b8c4cf954630e9, type: 3} + m_Name: + m_EditorClassIdentifier: + m_TrackedObjects: + - rid: 8021623883140169739 + references: + version: 2 + RefIds: + - rid: 8021623883140169739 + type: {class: TrackedUGuiGraphic, ns: UnityEngine.Localization.PropertyVariants.TrackedObjects, + asm: Unity.Localization} + data: + m_Target: {fileID: 7198143098074655042} + m_TrackedProperties: + items: + - rid: 8021623883140169740 + m_UpdateType: 0 + - rid: 8021623883140169740 + type: {class: LocalizedStringProperty, ns: UnityEngine.Localization.PropertyVariants.TrackedProperties, + asm: Unity.Localization} + data: + m_Localized: + m_TableReference: + m_TableCollectionName: GUID:c84355079ab3f3e4f8f3812258805f86 + m_TableEntryReference: + m_KeyId: 15524391402909696 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_PropertyPath: m_text +--- !u!1 &5048206632594256402 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -6051,212 +6380,58 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 3554585349599419749} - - component: {fileID: 2124419336652034620} - - component: {fileID: 1855359805432446158} + - component: {fileID: 3576301794080265196} + - component: {fileID: 480163635885148388} m_Layer: 16 - m_Name: Sketchfab_BackPlate + m_Name: DriveInfoElements m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &3554585349599419749 + m_IsActive: 0 +--- !u!4 &3576301794080265196 Transform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6877995767082855847} - m_LocalRotation: {x: -0.7071068, y: -0, z: -0, w: 0.7071067} - m_LocalPosition: {x: 0.53499997, y: 0.2550001, z: -0.005} - m_LocalScale: {x: 32, y: 32, z: 20} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 534589999851858800} - m_RootOrder: 0 + m_GameObject: {fileID: 5048206632594256402} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0.13499999, z: 0} + m_LocalScale: {x: 0.85, y: 0.8500001, z: 0.8500001} + m_ConstrainProportionsScale: 1 + m_Children: + - {fileID: 3755039154609302241} + - {fileID: 6679582736177907422} + - {fileID: 7566473728865432861} + - {fileID: 5521146392998997215} + m_Father: {fileID: 8645625734765961102} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!33 &2124419336652034620 -MeshFilter: +--- !u!114 &480163635885148388 +MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6877995767082855847} - m_Mesh: {fileID: 4300002, guid: 3efe5b86b55995545a231ce66a53b402, type: 3} ---- !u!23 &1855359805432446158 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 6877995767082855847} - m_Enabled: 1 - m_CastShadows: 0 - m_ReceiveShadows: 0 - m_DynamicOccludee: 1 - m_StaticShadowCaster: 0 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RayTraceProcedural: 0 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 2100000, guid: 8fe8230ee7ae32a4eb7fe6d5df34ebd4, type: 2} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 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 - m_AdditionalVertexStreams: {fileID: 0} ---- !u!1 &7241757417913730636 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 2399947737502410141} - - component: {fileID: 7967378821529834859} - - component: {fileID: 1423734451789490328} - m_Layer: 16 - m_Name: Google_BackPlate - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &2399947737502410141 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7241757417913730636} - m_LocalRotation: {x: -0.7071068, y: -0, z: -0, w: 0.7071067} - m_LocalPosition: {x: -0.622, y: 0.2550001, z: -0.005} - m_LocalScale: {x: 32, y: 32, z: 20} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 7741920746089690377} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!33 &7967378821529834859 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7241757417913730636} - m_Mesh: {fileID: 4300002, guid: 3efe5b86b55995545a231ce66a53b402, type: 3} ---- !u!23 &1423734451789490328 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7241757417913730636} - m_Enabled: 1 - m_CastShadows: 0 - m_ReceiveShadows: 0 - m_DynamicOccludee: 1 - m_StaticShadowCaster: 0 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RayTraceProcedural: 0 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 2100000, guid: 8fe8230ee7ae32a4eb7fe6d5df34ebd4, type: 2} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 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 - m_AdditionalVertexStreams: {fileID: 0} ---- !u!1 &7292193688806996409 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1411852402157678472} - m_Layer: 16 - m_Name: Google_SignedInElements - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &1411852402157678472 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7292193688806996409} - 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_ConstrainProportionsScale: 0 - m_Children: - - {fileID: 8645625734912766616} - - {fileID: 8645625732761162234} - - {fileID: 8425076696762416562} - - {fileID: 1741904442304953456} - - {fileID: 6692607038900794975} - m_Father: {fileID: 5854179938074699431} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &7389499574749059798 -GameObject: + m_GameObject: {fileID: 5048206632594256402} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 20ac3005e19346a4296a8f6a73363832, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!1 &5111218671440306906 +GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 9062749716723118463} - - component: {fileID: 5851412377445962644} - - component: {fileID: 5204209675494704913} - - component: {fileID: 495762216464883552} + - component: {fileID: 9209058213459650767} + - component: {fileID: 8820378468166149913} + - component: {fileID: 1547790019101272354} + - component: {fileID: 3197312481833515046} m_Layer: 0 m_Name: Title m_TagString: Untagged @@ -6264,33 +6439,32 @@ GameObject: m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!224 &9062749716723118463 +--- !u!224 &9209058213459650767 RectTransform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7389499574749059798} + m_GameObject: {fileID: 5111218671440306906} m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: -0.0025} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] - m_Father: {fileID: 1766577842652504206} - m_RootOrder: 0 + m_Father: {fileID: 4825048073929942150} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} m_AnchoredPosition: {x: 0, y: 0.5} m_SizeDelta: {x: 2.27, y: 0.3} m_Pivot: {x: 0.5, y: 0.5} ---- !u!23 &5851412377445962644 +--- !u!23 &8820378468166149913 MeshRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7389499574749059798} + m_GameObject: {fileID: 5111218671440306906} m_Enabled: 1 m_CastShadows: 0 m_ReceiveShadows: 0 @@ -6326,13 +6500,13 @@ MeshRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!114 &5204209675494704913 +--- !u!114 &1547790019101272354 MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7389499574749059798} + m_GameObject: {fileID: 5111218671440306906} m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 9541d86e2fd84c1d9990edf0852d74ab, type: 3} @@ -6346,7 +6520,7 @@ MonoBehaviour: m_OnCullStateChanged: m_PersistentCalls: m_Calls: [] - m_text: Error + m_text: Share with Google m_isRightToLeft: 0 m_fontAsset: {fileID: 11400000, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} m_sharedMaterial: {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} @@ -6416,35 +6590,35 @@ MonoBehaviour: _SortingLayerID: 0 _SortingOrder: 0 m_hasFontAssetChanged: 0 - m_renderer: {fileID: 5851412377445962644} + m_renderer: {fileID: 8820378468166149913} m_maskType: 0 ---- !u!114 &495762216464883552 +--- !u!114 &3197312481833515046 MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7389499574749059798} + m_GameObject: {fileID: 5111218671440306906} m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 69beb381e244f92449b8c4cf954630e9, type: 3} m_Name: m_EditorClassIdentifier: m_TrackedObjects: - - rid: 3215294302546034854 + - rid: 3215294302546034850 references: version: 2 RefIds: - - rid: 3215294302546034854 + - rid: 3215294302546034850 type: {class: TrackedUGuiGraphic, ns: UnityEngine.Localization.PropertyVariants.TrackedObjects, asm: Unity.Localization} data: - m_Target: {fileID: 5204209675494704913} + m_Target: {fileID: 1547790019101272354} m_TrackedProperties: items: - - rid: 3215294302546034855 + - rid: 3215294302546034851 m_UpdateType: 0 - - rid: 3215294302546034855 + - rid: 3215294302546034851 type: {class: LocalizedStringProperty, ns: UnityEngine.Localization.PropertyVariants.TrackedProperties, asm: Unity.Localization} data: @@ -6452,13 +6626,13 @@ MonoBehaviour: m_TableReference: m_TableCollectionName: GUID:c84355079ab3f3e4f8f3812258805f86 m_TableEntryReference: - m_KeyId: 147094550989828096 + m_KeyId: 76137928887689216 m_Key: m_FallbackState: 0 m_WaitForCompletion: 0 m_LocalVariables: [] m_PropertyPath: m_text ---- !u!1 &7464697824948226506 +--- !u!1 &5123262806756250226 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -6466,46 +6640,46 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 5753424830644711893} - - component: {fileID: 5785604700358356680} - - component: {fileID: 4813821531570180984} + - component: {fileID: 5208561973859313428} + - component: {fileID: 7929569316632562742} + - component: {fileID: 8052510225724890313} m_Layer: 16 - m_Name: Sketchfab_BackPlate + m_Name: Background m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!4 &5753424830644711893 +--- !u!4 &5208561973859313428 Transform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7464697824948226506} - m_LocalRotation: {x: -0.7071068, y: -0, z: -0, w: 0.7071067} - m_LocalPosition: {x: 0.621, y: -0.151, z: -0.005} - m_LocalScale: {x: 47, y: 49.999924, z: 74.2} + m_GameObject: {fileID: 5123262806756250226} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0.045} + m_LocalScale: {x: 2, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] - m_Father: {fileID: 529827201699571093} - m_RootOrder: 3 + m_Father: {fileID: 7893921961113671483} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!33 &5785604700358356680 +--- !u!33 &7929569316632562742 MeshFilter: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7464697824948226506} - m_Mesh: {fileID: 4300002, guid: 3efe5b86b55995545a231ce66a53b402, type: 3} ---- !u!23 &4813821531570180984 + m_GameObject: {fileID: 5123262806756250226} + m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &8052510225724890313 MeshRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7464697824948226506} + m_GameObject: {fileID: 5123262806756250226} m_Enabled: 1 m_CastShadows: 0 m_ReceiveShadows: 0 @@ -6519,7 +6693,7 @@ MeshRenderer: m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 2100000, guid: 8fe8230ee7ae32a4eb7fe6d5df34ebd4, type: 2} + - {fileID: 2100000, guid: 0ead8b8e224bcf040862605f5eed7211, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 @@ -6528,7 +6702,7 @@ MeshRenderer: m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 m_ReceiveGI: 1 - m_PreserveUVs: 0 + m_PreserveUVs: 1 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 m_StitchLightmapSeams: 0 @@ -6541,7 +6715,7 @@ MeshRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!1 &7600327135675325717 +--- !u!1 &5301811399408650331 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -6549,60 +6723,60 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 3392034205142368857} - - component: {fileID: 6946978540861440256} - - component: {fileID: 2741931446377032717} + - component: {fileID: 1182483975005714860} + - component: {fileID: 6161329202685458175} + - component: {fileID: 6793863180280690477} m_Layer: 16 - m_Name: PhotoBGW + m_Name: Dividor m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!4 &3392034205142368857 +--- !u!4 &1182483975005714860 Transform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7600327135675325717} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0.0022857143} - m_LocalScale: {x: 1.1, y: 1.1, z: 1.1} + m_GameObject: {fileID: 5301811399408650331} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: -0.151, z: -0.005} + m_LocalScale: {x: 0.01, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] - m_Father: {fileID: 5621771514230647440} - m_RootOrder: 0 + m_Father: {fileID: 8645625735416266758} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!33 &6946978540861440256 +--- !u!33 &6161329202685458175 MeshFilter: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7600327135675325717} + m_GameObject: {fileID: 5301811399408650331} m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} ---- !u!23 &2741931446377032717 +--- !u!23 &6793863180280690477 MeshRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7600327135675325717} + m_GameObject: {fileID: 5301811399408650331} m_Enabled: 1 m_CastShadows: 0 m_ReceiveShadows: 0 m_DynamicOccludee: 1 m_StaticShadowCaster: 0 m_MotionVectors: 1 - m_LightProbeUsage: 0 + m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 2100000, guid: 0c298b4a41e7c5b4daf56d8987a83788, type: 2} + - {fileID: 2100000, guid: 8fe8230ee7ae32a4eb7fe6d5df34ebd4, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 @@ -6624,7 +6798,7 @@ MeshRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!1 &7620355729290749329 +--- !u!1 &5315453881601467229 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -6632,79 +6806,43 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 534589999851858800} - m_Layer: 16 - m_Name: Sketchfab_SignedOutElements - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &534589999851858800 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7620355729290749329} - 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_ConstrainProportionsScale: 0 - m_Children: - - {fileID: 3554585349599419749} - - {fileID: 4946117081540083272} - - {fileID: 5383840309452991305} - - {fileID: 4700142148089133932} - - {fileID: 181638217984195686} - m_Father: {fileID: 149137880941958609} - m_RootOrder: 1 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &7725770829448276136 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 5383840309452991305} - - component: {fileID: 1591778397208625653} - - component: {fileID: 3852620365131538827} + - component: {fileID: 1583684570998085433} + - component: {fileID: 5194402002804098867} + - component: {fileID: 8290597564335685000} + - component: {fileID: 2511332541157942654} m_Layer: 16 - m_Name: Sketchfab_Text + m_Name: Text m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!224 &5383840309452991305 +--- !u!224 &1583684570998085433 RectTransform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7725770829448276136} + m_GameObject: {fileID: 5315453881601467229} m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: -0.01} - m_LocalScale: {x: 1, y: 1, z: 1} + m_LocalPosition: {x: 0, y: 0, z: -0.009999992} + m_LocalScale: {x: 4, y: 4, z: 2.857143} m_ConstrainProportionsScale: 0 m_Children: [] - m_Father: {fileID: 534589999851858800} - m_RootOrder: 2 + m_Father: {fileID: 7893921961113671483} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMax: {x: 0.5, y: 0.5} - m_AnchoredPosition: {x: 0.428, y: 0.3524501} - m_SizeDelta: {x: 20, y: 5} - m_Pivot: {x: 0, y: 1} ---- !u!23 &1591778397208625653 + m_AnchoredPosition: {x: -0.20199999, y: 0} + m_SizeDelta: {x: 0.3, y: 0.15} + m_Pivot: {x: 0, y: 0.5} +--- !u!23 &5194402002804098867 MeshRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7725770829448276136} + m_GameObject: {fileID: 5315453881601467229} m_Enabled: 1 m_CastShadows: 0 m_ReceiveShadows: 0 @@ -6740,13 +6878,13 @@ MeshRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!114 &3852620365131538827 +--- !u!114 &8290597564335685000 MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7725770829448276136} + m_GameObject: {fileID: 5315453881601467229} m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 9541d86e2fd84c1d9990edf0852d74ab, type: 3} @@ -6760,7 +6898,7 @@ MonoBehaviour: m_OnCullStateChanged: m_PersistentCalls: m_Calls: [] - m_text: Sketchfab + m_text: SIGN IN m_isRightToLeft: 0 m_fontAsset: {fileID: 11400000, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} m_sharedMaterial: {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} @@ -6787,15 +6925,15 @@ MonoBehaviour: m_faceColor: serializedVersion: 2 rgba: 4294967295 - m_fontSize: 1.35 - m_fontSizeBase: 1.35 + m_fontSize: 0.86 + m_fontSizeBase: 0.86 m_fontWeight: 400 m_enableAutoSizing: 0 m_fontSizeMin: 18 m_fontSizeMax: 72 m_fontStyle: 0 m_HorizontalAlignment: 1 - m_VerticalAlignment: 256 + m_VerticalAlignment: 512 m_textAlignment: 65535 m_characterSpacing: 0 m_wordSpacing: 0 @@ -6830,9 +6968,49 @@ MonoBehaviour: _SortingLayerID: 0 _SortingOrder: 0 m_hasFontAssetChanged: 0 - m_renderer: {fileID: 1591778397208625653} + m_renderer: {fileID: 5194402002804098867} m_maskType: 0 ---- !u!1 &7844204848832429112 +--- !u!114 &2511332541157942654 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5315453881601467229} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 69beb381e244f92449b8c4cf954630e9, type: 3} + m_Name: + m_EditorClassIdentifier: + m_TrackedObjects: + - rid: 3215294302546034846 + references: + version: 2 + RefIds: + - rid: 3215294302546034846 + type: {class: TrackedUGuiGraphic, ns: UnityEngine.Localization.PropertyVariants.TrackedObjects, + asm: Unity.Localization} + data: + m_Target: {fileID: 8290597564335685000} + m_TrackedProperties: + items: + - rid: 3215294302546034847 + m_UpdateType: 0 + - rid: 3215294302546034847 + type: {class: LocalizedStringProperty, ns: UnityEngine.Localization.PropertyVariants.TrackedProperties, + asm: Unity.Localization} + data: + m_Localized: + m_TableReference: + m_TableCollectionName: GUID:c84355079ab3f3e4f8f3812258805f86 + m_TableEntryReference: + m_KeyId: 7933561489039360 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_PropertyPath: m_text +--- !u!1 &5403683023149528791 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -6840,60 +7018,57 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 8006143071345660080} - - component: {fileID: 8207801876785030697} - - component: {fileID: 5143970747722748072} - m_Layer: 16 - m_Name: Background + - component: {fileID: 4704522903857296483} + - component: {fileID: 6212349802531054436} + - component: {fileID: 8705749884328266341} + - component: {fileID: 832193050044176433} + m_Layer: 0 + m_Name: Description m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!4 &8006143071345660080 -Transform: +--- !u!224 &4704522903857296483 +RectTransform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7844204848832429112} + m_GameObject: {fileID: 5403683023149528791} m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0.0021666286, y: 0, z: 0} + m_LocalPosition: {x: 0, y: 0, z: -0.0025} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] - m_Father: {fileID: 7338107887349877872} - m_RootOrder: 1 + m_Father: {fileID: 3457603883277620212} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!33 &8207801876785030697 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7844204848832429112} - m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} ---- !u!23 &5143970747722748072 + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0.058} + m_SizeDelta: {x: 2.5, y: 0.7} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!23 &6212349802531054436 MeshRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 7844204848832429112} + m_GameObject: {fileID: 5403683023149528791} m_Enabled: 1 m_CastShadows: 0 m_ReceiveShadows: 0 m_DynamicOccludee: 1 m_StaticShadowCaster: 0 m_MotionVectors: 1 - m_LightProbeUsage: 1 + m_LightProbeUsage: 0 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 2100000, guid: 39d7053101c6e8e4b8d692eddc65d2b2, type: 2} + - {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 @@ -6902,7 +7077,7 @@ MeshRenderer: m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 m_ReceiveGI: 1 - m_PreserveUVs: 1 + m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 m_StitchLightmapSeams: 0 @@ -6915,128 +7090,13 @@ MeshRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!1 &8025577052483214110 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 4825048073929942150} - m_Layer: 16 - m_Name: GoogleInfoElements - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 0 ---- !u!4 &4825048073929942150 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8025577052483214110} - 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_ConstrainProportionsScale: 0 - m_Children: - - {fileID: 9209058213459650767} - - {fileID: 8844894437526037228} - - {fileID: 6721629502030059466} - m_Father: {fileID: 8645625734765961102} - m_RootOrder: 2 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &8156563521135199732 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 3376029733079660750} - - component: {fileID: 4750026522078451160} - - component: {fileID: 8973140315319083013} - - component: {fileID: 1977399286951791455} - m_Layer: 16 - m_Name: Text - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!224 &3376029733079660750 -RectTransform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8156563521135199732} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: -0.009999992} - m_LocalScale: {x: 4, y: 4, z: 2.857143} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 181638217984195686} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0.5, y: 0.5} - m_AnchorMax: {x: 0.5, y: 0.5} - m_AnchoredPosition: {x: -0.202, y: 0} - m_SizeDelta: {x: 0.3, y: 0.15} - m_Pivot: {x: 0, y: 0.5} ---- !u!23 &4750026522078451160 -MeshRenderer: +--- !u!114 &8705749884328266341 +MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8156563521135199732} - m_Enabled: 1 - m_CastShadows: 0 - m_ReceiveShadows: 0 - m_DynamicOccludee: 1 - m_StaticShadowCaster: 0 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RayTraceProcedural: 0 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - 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 - m_AdditionalVertexStreams: {fileID: 0} ---- !u!114 &8973140315319083013 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8156563521135199732} + m_GameObject: {fileID: 5403683023149528791} m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 9541d86e2fd84c1d9990edf0852d74ab, type: 3} @@ -7050,7 +7110,9 @@ MonoBehaviour: m_OnCullStateChanged: m_PersistentCalls: m_Calls: [] - m_text: SIGN IN + m_text: 'Sign in to a Sketchfab account to allow + + uploading to Sketchfab.' m_isRightToLeft: 0 m_fontAsset: {fileID: 11400000, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} m_sharedMaterial: {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} @@ -7059,8 +7121,8 @@ MonoBehaviour: m_fontMaterials: [] m_fontColor32: serializedVersion: 2 - rgba: 4294967295 - m_fontColor: {r: 1, g: 1, b: 1, a: 1} + rgba: 4286085240 + m_fontColor: {r: 0.47058824, g: 0.47058824, b: 0.47058824, a: 1} m_enableVertexGradient: 0 m_colorMode: 3 m_fontColorGradient: @@ -7077,14 +7139,14 @@ MonoBehaviour: m_faceColor: serializedVersion: 2 rgba: 4294967295 - m_fontSize: 0.86 - m_fontSizeBase: 0.86 + m_fontSize: 1.275 + m_fontSizeBase: 1.275 m_fontWeight: 400 m_enableAutoSizing: 0 m_fontSizeMin: 18 m_fontSizeMax: 72 m_fontStyle: 0 - m_HorizontalAlignment: 1 + m_HorizontalAlignment: 2 m_VerticalAlignment: 512 m_textAlignment: 65535 m_characterSpacing: 0 @@ -7120,35 +7182,35 @@ MonoBehaviour: _SortingLayerID: 0 _SortingOrder: 0 m_hasFontAssetChanged: 0 - m_renderer: {fileID: 4750026522078451160} + m_renderer: {fileID: 6212349802531054436} m_maskType: 0 ---- !u!114 &1977399286951791455 +--- !u!114 &832193050044176433 MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8156563521135199732} + m_GameObject: {fileID: 5403683023149528791} m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 69beb381e244f92449b8c4cf954630e9, type: 3} m_Name: m_EditorClassIdentifier: m_TrackedObjects: - - rid: 3215294302546034848 + - rid: 3215294302546034856 references: version: 2 RefIds: - - rid: 3215294302546034848 + - rid: 3215294302546034856 type: {class: TrackedUGuiGraphic, ns: UnityEngine.Localization.PropertyVariants.TrackedObjects, asm: Unity.Localization} data: - m_Target: {fileID: 8973140315319083013} + m_Target: {fileID: 8705749884328266341} m_TrackedProperties: items: - - rid: 3215294302546034849 + - rid: 3215294302546034857 m_UpdateType: 0 - - rid: 3215294302546034849 + - rid: 3215294302546034857 type: {class: LocalizedStringProperty, ns: UnityEngine.Localization.PropertyVariants.TrackedProperties, asm: Unity.Localization} data: @@ -7156,13 +7218,13 @@ MonoBehaviour: m_TableReference: m_TableCollectionName: GUID:c84355079ab3f3e4f8f3812258805f86 m_TableEntryReference: - m_KeyId: 7933561489039360 + m_KeyId: 76138521224077312 m_Key: m_FallbackState: 0 m_WaitForCompletion: 0 m_LocalVariables: [] m_PropertyPath: m_text ---- !u!1 &8203317146764388448 +--- !u!1 &5419396676487616149 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -7170,46 +7232,48 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 5384230387207399056} - - component: {fileID: 1440642196620937798} - - component: {fileID: 7293745301264864356} + - component: {fileID: 5446221535905318599} + - component: {fileID: 5255334288434809734} + - component: {fileID: 1369930125958929065} + - component: {fileID: 4730200966117401982} + - component: {fileID: 712852433553107461} m_Layer: 16 - m_Name: Background + m_Name: Google_SignOut m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!4 &5384230387207399056 +--- !u!4 &5446221535905318599 Transform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8203317146764388448} + m_GameObject: {fileID: 5419396676487616149} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0.0021666286, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} + m_LocalPosition: {x: -0.398, y: -0.242, z: -0.06} + m_LocalScale: {x: 0.35, y: 0.35, z: 0.35} m_ConstrainProportionsScale: 0 m_Children: [] - m_Father: {fileID: 6721629502030059466} - m_RootOrder: 1 + m_Father: {fileID: 7741920746089690377} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!33 &1440642196620937798 +--- !u!33 &5255334288434809734 MeshFilter: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8203317146764388448} + m_GameObject: {fileID: 5419396676487616149} m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} ---- !u!23 &7293745301264864356 +--- !u!23 &1369930125958929065 MeshRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8203317146764388448} + m_GameObject: {fileID: 5419396676487616149} m_Enabled: 1 m_CastShadows: 0 m_ReceiveShadows: 0 @@ -7223,7 +7287,7 @@ MeshRenderer: m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 2100000, guid: 39d7053101c6e8e4b8d692eddc65d2b2, type: 2} + - {fileID: 2100000, guid: 3c8ca511828182747a0b79564892ec57, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 @@ -7245,7 +7309,106 @@ MeshRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!1 &8230375728890308425 +--- !u!114 &4730200966117401982 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5419396676487616149} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 6c6859eec74651247968d56b594ac313, type: 3} + m_Name: + m_EditorClassIdentifier: + m_DescriptionType: 0 + m_DescriptionYOffset: 0 + m_DescriptionText: POPUP_ACCOUNTS_SIGNOUT_BUTTON_DESCRIPTION + m_LocalizedDescription: + m_TableReference: + m_TableCollectionName: GUID:c84355079ab3f3e4f8f3812258805f86 + m_TableEntryReference: + m_KeyId: 15522362785837056 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_DescriptionTextExtra: + m_LocalizedDescriptionExtra: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_DescriptionActivateSpeed: 12 + m_DescriptionZScale: 1 + m_ButtonTexture: {fileID: 2800000, guid: 6bd8742b210a6444e85b5c86f80ffebc, type: 3} + m_AtlasTexture: 1 + m_ToggleButton: 0 + m_LongPressReleaseButton: 0 + m_ButtonHasPressedAudio: 1 + m_ZAdjustHover: -0.02 + m_ZAdjustClick: 0.05 + m_HoverScale: 1.1 + m_HoverBoxColliderGrow: 0.2 + m_AddOverlay: 0 + m_Command: 27 + m_CommandParam: 1 + m_CommandParam2: -1 + m_RequiresPopup: 0 + m_CenterPopupOnButton: 0 + m_PopupOffset: {x: 0, y: 0, z: 0} + m_PopupText: + m_LocalizedPopup: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_ToggleOnDescription: + m_LocalizedToggleOnDescription: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_ToggleOnTexture: {fileID: 0} + m_AllowUnavailable: 0 + m_LinkedUIObject: {fileID: 0} + references: + version: 2 + RefIds: [] +--- !u!65 &712852433553107461 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5419396676487616149} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Size: {x: 1, y: 1.0000001, z: 0.1} + m_Center: {x: 0, y: 0, z: -0.01} +--- !u!1 &5427861527217224720 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -7253,60 +7416,64 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 1506107517258712976} - - component: {fileID: 1482784536010354649} - - component: {fileID: 5311018060250719400} - m_Layer: 16 - m_Name: Google_Logo + - component: {fileID: 6721629502030059466} + - component: {fileID: 744816621245303203} + - component: {fileID: 5315415322598248231} + - component: {fileID: 7149889851386687525} + - component: {fileID: 5696691115232969362} + m_Layer: 14 + m_Name: ConfirmationButton m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!4 &1506107517258712976 +--- !u!4 &6721629502030059466 Transform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8230375728890308425} + m_GameObject: {fileID: 5427861527217224720} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: -0.9828, y: 0.26200008, z: -0.01} - m_LocalScale: {x: 0.2649999, y: 0.2649999, z: 0.2649999} + m_LocalPosition: {x: 0, y: -0.434, z: -0.08} + m_LocalScale: {x: 0.6, y: 0.29999998, z: 0.29999998} m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 1432546188030660464} - m_RootOrder: 1 + m_Children: + - {fileID: 3215585481372348197} + - {fileID: 5384230387207399056} + m_Father: {fileID: 4825048073929942150} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!33 &1482784536010354649 +--- !u!33 &744816621245303203 MeshFilter: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8230375728890308425} + m_GameObject: {fileID: 5427861527217224720} m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} ---- !u!23 &5311018060250719400 +--- !u!23 &5315415322598248231 MeshRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8230375728890308425} - m_Enabled: 1 + m_GameObject: {fileID: 5427861527217224720} + m_Enabled: 0 m_CastShadows: 0 m_ReceiveShadows: 0 m_DynamicOccludee: 1 m_StaticShadowCaster: 0 m_MotionVectors: 1 - m_LightProbeUsage: 1 + m_LightProbeUsage: 0 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 2100000, guid: 63abc547c73548943a62755aac9edc7b, type: 2} + - {fileID: 2100000, guid: 3c8ca511828182747a0b79564892ec57, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 @@ -7328,52 +7495,156 @@ MeshRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!1 &8300865502376788124 -GameObject: +--- !u!65 &7149889851386687525 +BoxCollider: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 3215585481372348197} - - component: {fileID: 4397428889506138906} - - component: {fileID: 7525156312729440484} - - component: {fileID: 7528125410182563106} - m_Layer: 16 - m_Name: Got it - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!224 &3215585481372348197 -RectTransform: + m_GameObject: {fileID: 5427861527217224720} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Size: {x: 1, y: 1, z: 0.01} + m_Center: {x: 0, y: 0, z: -0.01} +--- !u!114 &5696691115232969362 +MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8300865502376788124} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: -0.029333334} - m_LocalScale: {x: 2.9528668, y: 5.9057336, z: 2.9528668} + m_GameObject: {fileID: 5427861527217224720} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fc12adcafa62a22458e635d2ee7e78b5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_DescriptionType: -1 + m_DescriptionYOffset: 0 + m_DescriptionText: + m_LocalizedDescription: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_DescriptionTextExtra: + m_LocalizedDescriptionExtra: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_DescriptionActivateSpeed: 12 + m_DescriptionZScale: 1 + m_ButtonTexture: {fileID: 0} + m_AtlasTexture: 0 + m_ToggleButton: 0 + m_LongPressReleaseButton: 0 + m_ButtonHasPressedAudio: 1 + m_ZAdjustHover: -0.02 + m_ZAdjustClick: 0.05 + m_HoverScale: 1.1 + m_HoverBoxColliderGrow: 0.2 + m_AddOverlay: 0 + m_Command: 0 + m_CommandParam: -1 + m_CommandParam2: -1 + m_RequiresPopup: 0 + m_CenterPopupOnButton: 0 + m_PopupOffset: {x: 0, y: 0, z: 0} + m_PopupText: + m_LocalizedPopup: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_ToggleOnDescription: + m_LocalizedToggleOnDescription: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_ToggleOnTexture: {fileID: 0} + m_AllowUnavailable: 0 + m_LinkedUIObject: {fileID: 0} + m_CommandIgnored: 0 + references: + version: 2 + RefIds: [] +--- !u!1 &5598400511041364639 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 9214833072643761372} + - component: {fileID: 3899858871660736573} + - component: {fileID: 5558472698597662980} + m_Layer: 16 + m_Name: Icosa_ProfilePhoto + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &9214833072643761372 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5598400511041364639} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0.621, y: 0.11, z: -0.010000025} + m_LocalScale: {x: 0.4, y: 0.4, z: 0.4} m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 6721629502030059466} - m_RootOrder: 0 + m_Children: + - {fileID: 8639010961277564811} + - {fileID: 8146115410073256732} + m_Father: {fileID: 8994260351568061772} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0.5, y: 0.5} - m_AnchorMax: {x: 0.5, y: 0.5} - m_AnchoredPosition: {x: 0.141, y: 0} - m_SizeDelta: {x: 0.25, y: 0.15} - m_Pivot: {x: 0.5, y: 0.5} ---- !u!23 &4397428889506138906 +--- !u!33 &3899858871660736573 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5598400511041364639} + m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &5558472698597662980 MeshRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8300865502376788124} + m_GameObject: {fileID: 5598400511041364639} m_Enabled: 1 m_CastShadows: 0 m_ReceiveShadows: 0 @@ -7387,7 +7658,7 @@ MeshRenderer: m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} + - {fileID: 2100000, guid: da7f0d43a22e3f24bbc517466728866f, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 @@ -7409,139 +7680,7 @@ MeshRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!114 &7525156312729440484 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8300865502376788124} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 9541d86e2fd84c1d9990edf0852d74ab, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Material: {fileID: 0} - m_Color: {r: 1, g: 1, b: 1, a: 1} - m_RaycastTarget: 1 - m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} - m_Maskable: 1 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_text: GOT IT - m_isRightToLeft: 0 - m_fontAsset: {fileID: 11400000, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} - m_sharedMaterial: {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} - m_fontSharedMaterials: [] - m_fontMaterial: {fileID: 0} - m_fontMaterials: [] - m_fontColor32: - serializedVersion: 2 - rgba: 4294967295 - m_fontColor: {r: 1, g: 1, b: 1, a: 1} - m_enableVertexGradient: 0 - m_colorMode: 3 - m_fontColorGradient: - topLeft: {r: 1, g: 1, b: 1, a: 1} - topRight: {r: 1, g: 1, b: 1, a: 1} - bottomLeft: {r: 1, g: 1, b: 1, a: 1} - bottomRight: {r: 1, g: 1, b: 1, a: 1} - m_fontColorGradientPreset: {fileID: 0} - m_spriteAsset: {fileID: 0} - m_tintAllSprites: 0 - m_StyleSheet: {fileID: 0} - m_TextStyleHashCode: -1183493901 - m_overrideHtmlColors: 0 - m_faceColor: - serializedVersion: 2 - rgba: 4294967295 - m_fontSize: 0.64 - m_fontSizeBase: 0.64 - m_fontWeight: 400 - m_enableAutoSizing: 0 - m_fontSizeMin: 18 - m_fontSizeMax: 72 - m_fontStyle: 0 - m_HorizontalAlignment: 2 - m_VerticalAlignment: 512 - m_textAlignment: 65535 - m_characterSpacing: 0 - m_wordSpacing: 0 - m_lineSpacing: 0 - m_lineSpacingMax: 0 - m_paragraphSpacing: 0 - m_charWidthMaxAdj: 0 - m_enableWordWrapping: 1 - m_wordWrappingRatios: 0.4 - m_overflowMode: 0 - m_linkedTextComponent: {fileID: 0} - parentLinkedComponent: {fileID: 0} - m_enableKerning: 1 - m_enableExtraPadding: 0 - checkPaddingRequired: 0 - m_isRichText: 1 - m_parseCtrlCharacters: 1 - m_isOrthographic: 0 - m_isCullingEnabled: 0 - m_horizontalMapping: 0 - m_verticalMapping: 0 - m_uvLineOffset: 0 - m_geometrySortingOrder: 0 - m_IsTextObjectScaleStatic: 0 - m_VertexBufferAutoSizeReduction: 0 - m_useMaxVisibleDescender: 1 - m_pageToDisplay: 1 - m_margin: {x: 0, y: 0, z: 0, w: 0} - m_isUsingLegacyAnimationComponent: 0 - m_isVolumetricText: 0 - _SortingLayer: 0 - _SortingLayerID: 0 - _SortingOrder: 0 - m_hasFontAssetChanged: 0 - m_renderer: {fileID: 4397428889506138906} - m_maskType: 0 ---- !u!114 &7528125410182563106 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8300865502376788124} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 69beb381e244f92449b8c4cf954630e9, type: 3} - m_Name: - m_EditorClassIdentifier: - m_TrackedObjects: - - rid: 3215294302546034844 - references: - version: 2 - RefIds: - - rid: 3215294302546034844 - type: {class: TrackedUGuiGraphic, ns: UnityEngine.Localization.PropertyVariants.TrackedObjects, - asm: Unity.Localization} - data: - m_Target: {fileID: 7525156312729440484} - m_TrackedProperties: - items: - - rid: 3215294302546034845 - m_UpdateType: 0 - - rid: 3215294302546034845 - type: {class: LocalizedStringProperty, ns: UnityEngine.Localization.PropertyVariants.TrackedProperties, - asm: Unity.Localization} - data: - m_Localized: - m_TableReference: - m_TableCollectionName: GUID:c84355079ab3f3e4f8f3812258805f86 - m_TableEntryReference: - m_KeyId: 76036746777255936 - m_Key: - m_FallbackState: 0 - m_WaitForCompletion: 0 - m_LocalVariables: [] - m_PropertyPath: m_text ---- !u!1 &8372598602804526943 +--- !u!1 &5649685825589421528 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -7549,35 +7688,34 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 1432546188030660464} + - component: {fileID: 6423827612944397798} m_Layer: 16 - m_Name: Google_SignedOutElements + m_Name: Sketchfab_ConfirmSignOutElements m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!4 &1432546188030660464 +--- !u!4 &6423827612944397798 Transform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8372598602804526943} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_GameObject: {fileID: 5649685825589421528} + serializedVersion: 2 + 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_ConstrainProportionsScale: 0 m_Children: - - {fileID: 8671432921432109627} - - {fileID: 1506107517258712976} - - {fileID: 277837882360728660} - - {fileID: 6952797202003472198} - - {fileID: 7893921961113671483} - m_Father: {fileID: 5854179938074699431} - m_RootOrder: 1 + - {fileID: 8245513620673000221} + - {fileID: 4111961635044152573} + - {fileID: 6124434747938532598} + - {fileID: 4120900520909079457} + m_Father: {fileID: 149137880941958609} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &8374217926999613278 +--- !u!1 &5782945728072830494 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -7585,91 +7723,60 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 1766577842652504206} + - component: {fileID: 7015353133639046746} + - component: {fileID: 7835309114794309555} + - component: {fileID: 8424331600989237328} m_Layer: 16 - m_Name: UnavilableElements + m_Name: Mesh m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 - m_IsActive: 0 ---- !u!4 &1766577842652504206 + m_IsActive: 1 +--- !u!4 &7015353133639046746 Transform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8374217926999613278} + m_GameObject: {fileID: 5782945728072830494} + serializedVersion: 2 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_LocalScale: {x: 0.65, y: 0.65, z: 1} m_ConstrainProportionsScale: 0 - m_Children: - - {fileID: 9062749716723118463} - - {fileID: 1698918594952708344} - m_Father: {fileID: 8645625734765961102} - m_RootOrder: 5 + m_Children: [] + m_Father: {fileID: 8121802616684643442} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &8485803142575213209 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1698918594952708344} - - component: {fileID: 1322583919428993473} - - component: {fileID: 3928356307148317847} - - component: {fileID: 4196125711076099861} - m_Layer: 0 - m_Name: Description - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!224 &1698918594952708344 -RectTransform: +--- !u!33 &7835309114794309555 +MeshFilter: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8485803142575213209} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: -0.0025} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 1766577842652504206} - m_RootOrder: 1 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0.5, y: 0.5} - m_AnchorMax: {x: 0.5, y: 0.5} - m_AnchoredPosition: {x: 0, y: 0.058} - m_SizeDelta: {x: 2.5, y: 0.7} - m_Pivot: {x: 0.5, y: 0.5} ---- !u!23 &1322583919428993473 + m_GameObject: {fileID: 5782945728072830494} + m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &8424331600989237328 MeshRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8485803142575213209} + m_GameObject: {fileID: 5782945728072830494} m_Enabled: 1 m_CastShadows: 0 m_ReceiveShadows: 0 m_DynamicOccludee: 1 m_StaticShadowCaster: 0 m_MotionVectors: 1 - m_LightProbeUsage: 0 + m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} + - {fileID: 2100000, guid: 0d7eb02b18ffb4c419fb75924cb900dc, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 @@ -7678,7 +7785,7 @@ MeshRenderer: m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 m_ReceiveGI: 1 - m_PreserveUVs: 0 + m_PreserveUVs: 1 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 m_StitchLightmapSeams: 0 @@ -7691,139 +7798,42 @@ MeshRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!114 &3928356307148317847 -MonoBehaviour: +--- !u!1 &5866976969575595662 +GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8485803142575213209} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 9541d86e2fd84c1d9990edf0852d74ab, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Material: {fileID: 0} - m_Color: {r: 1, g: 1, b: 1, a: 1} - m_RaycastTarget: 1 - m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} - m_Maskable: 1 - m_OnCullStateChanged: - m_PersistentCalls: - m_Calls: [] - m_text: Accounts are temporarily\nunavailable on this platform. - m_isRightToLeft: 0 - m_fontAsset: {fileID: 11400000, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} - m_sharedMaterial: {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} - m_fontSharedMaterials: [] - m_fontMaterial: {fileID: 0} - m_fontMaterials: [] - m_fontColor32: - serializedVersion: 2 - rgba: 4286085240 - m_fontColor: {r: 0.47058824, g: 0.47058824, b: 0.47058824, a: 1} - m_enableVertexGradient: 0 - m_colorMode: 3 - m_fontColorGradient: - topLeft: {r: 1, g: 1, b: 1, a: 1} - topRight: {r: 1, g: 1, b: 1, a: 1} - bottomLeft: {r: 1, g: 1, b: 1, a: 1} - bottomRight: {r: 1, g: 1, b: 1, a: 1} - m_fontColorGradientPreset: {fileID: 0} - m_spriteAsset: {fileID: 0} - m_tintAllSprites: 0 - m_StyleSheet: {fileID: 0} - m_TextStyleHashCode: -1183493901 - m_overrideHtmlColors: 0 - m_faceColor: - serializedVersion: 2 - rgba: 4294967295 - m_fontSize: 1.275 - m_fontSizeBase: 1.275 - m_fontWeight: 400 - m_enableAutoSizing: 0 - m_fontSizeMin: 18 - m_fontSizeMax: 72 - m_fontStyle: 0 - m_HorizontalAlignment: 2 - m_VerticalAlignment: 512 - m_textAlignment: 65535 - m_characterSpacing: 0 - m_wordSpacing: 0 - m_lineSpacing: 0 - m_lineSpacingMax: 0 - m_paragraphSpacing: 0 - m_charWidthMaxAdj: 0 - m_enableWordWrapping: 1 - m_wordWrappingRatios: 0.4 - m_overflowMode: 0 - m_linkedTextComponent: {fileID: 0} - parentLinkedComponent: {fileID: 0} - m_enableKerning: 1 - m_enableExtraPadding: 0 - checkPaddingRequired: 0 - m_isRichText: 1 - m_parseCtrlCharacters: 1 - m_isOrthographic: 0 - m_isCullingEnabled: 0 - m_horizontalMapping: 0 - m_verticalMapping: 0 - m_uvLineOffset: 0 - m_geometrySortingOrder: 0 - m_IsTextObjectScaleStatic: 0 - m_VertexBufferAutoSizeReduction: 0 - m_useMaxVisibleDescender: 1 - m_pageToDisplay: 1 - m_margin: {x: 0, y: 0, z: 0, w: 0} - m_isUsingLegacyAnimationComponent: 0 - m_isVolumetricText: 0 - _SortingLayer: 0 - _SortingLayerID: 0 - _SortingOrder: 0 - m_hasFontAssetChanged: 0 - m_renderer: {fileID: 1322583919428993473} - m_maskType: 0 ---- !u!114 &4196125711076099861 -MonoBehaviour: + serializedVersion: 6 + m_Component: + - component: {fileID: 529827201699571093} + m_Layer: 16 + m_Name: Sketchfab_SignedInElements + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &529827201699571093 +Transform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8485803142575213209} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 69beb381e244f92449b8c4cf954630e9, type: 3} - m_Name: - m_EditorClassIdentifier: - m_TrackedObjects: - - rid: 3215294302546034856 - references: - version: 2 - RefIds: - - rid: 3215294302546034856 - type: {class: TrackedUGuiGraphic, ns: UnityEngine.Localization.PropertyVariants.TrackedObjects, - asm: Unity.Localization} - data: - m_Target: {fileID: 3928356307148317847} - m_TrackedProperties: - items: - - rid: 3215294302546034857 - m_UpdateType: 0 - - rid: 3215294302546034857 - type: {class: LocalizedStringProperty, ns: UnityEngine.Localization.PropertyVariants.TrackedProperties, - asm: Unity.Localization} - data: - m_Localized: - m_TableReference: - m_TableCollectionName: GUID:c84355079ab3f3e4f8f3812258805f86 - m_TableEntryReference: - m_KeyId: 147094689821290496 - m_Key: - m_FallbackState: 0 - m_WaitForCompletion: 0 - m_LocalVariables: [] - m_PropertyPath: m_text ---- !u!1 &8579567244815457455 + m_GameObject: {fileID: 5866976969575595662} + serializedVersion: 2 + 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_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 7314565180282189882} + - {fileID: 5621771514230647440} + - {fileID: 90735575297890764} + - {fileID: 5753424830644711893} + m_Father: {fileID: 149137880941958609} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &5921053250823053932 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -7831,66 +7841,60 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 1741904442304953456} - - component: {fileID: 1069378607617687420} - - component: {fileID: 9098812290505878358} - - component: {fileID: 215621484757398494} - - component: {fileID: 2602589182038582116} + - component: {fileID: 798000693479046927} + - component: {fileID: 1551091070195428418} + - component: {fileID: 3372310621534254453} m_Layer: 16 - m_Name: Drive_Link + m_Name: IconEnabled m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!4 &1741904442304953456 +--- !u!4 &798000693479046927 Transform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8579567244815457455} + m_GameObject: {fileID: 5921053250823053932} + serializedVersion: 2 m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: -0.62, y: -0.576, z: -0.02500001} - m_LocalScale: {x: 0.7, y: 0.18, z: 1} + m_LocalPosition: {x: -0.33714277, y: -0.011110305, z: -0.024999999} + m_LocalScale: {x: 0.21428569, y: 0.8333332, z: 0.15} m_ConstrainProportionsScale: 0 - m_Children: - - {fileID: 798000693479046927} - - {fileID: 1180802039870758397} - - {fileID: 4153333614772809210} - - {fileID: 7758143906596955047} - m_Father: {fileID: 1411852402157678472} - m_RootOrder: 3 + m_Children: [] + m_Father: {fileID: 1741904442304953456} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!33 &1069378607617687420 +--- !u!33 &1551091070195428418 MeshFilter: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8579567244815457455} + m_GameObject: {fileID: 5921053250823053932} m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} ---- !u!23 &9098812290505878358 +--- !u!23 &3372310621534254453 MeshRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8579567244815457455} + m_GameObject: {fileID: 5921053250823053932} m_Enabled: 1 m_CastShadows: 0 m_ReceiveShadows: 0 m_DynamicOccludee: 1 m_StaticShadowCaster: 0 m_MotionVectors: 1 - m_LightProbeUsage: 1 + m_LightProbeUsage: 0 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 2100000, guid: c731e5e6519d8354094a034ff2457c95, type: 2} + - {fileID: 2100000, guid: 3f00bfbfa437f004888833cf848a2416, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 @@ -7899,7 +7903,7 @@ MeshRenderer: m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 m_ReceiveGI: 1 - m_PreserveUVs: 1 + m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 m_StitchLightmapSeams: 0 @@ -7912,13 +7916,98 @@ MeshRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!114 &215621484757398494 +--- !u!1 &5978289847150237173 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2403478784508930027} + - component: {fileID: 899810967416512585} + - component: {fileID: 4794093715842536848} + - component: {fileID: 8216506891502149021} + - component: {fileID: 2329669131580351156} + m_Layer: 16 + m_Name: Icosa_Info + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &2403478784508930027 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5978289847150237173} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 1.046, y: 0.2620001, z: -0.025} + m_LocalScale: {x: 0.2, y: 0.2, z: 0.2} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1000721931266647293} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!33 &899810967416512585 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5978289847150237173} + m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &4794093715842536848 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5978289847150237173} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 0 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 3c8ca511828182747a0b79564892ec57, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 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 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!114 &8216506891502149021 MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8579567244815457455} + m_GameObject: {fileID: 5978289847150237173} m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: fc12adcafa62a22458e635d2ee7e78b5, type: 3} @@ -7948,18 +8037,18 @@ MonoBehaviour: m_LocalVariables: [] m_DescriptionActivateSpeed: 12 m_DescriptionZScale: 1 - m_ButtonTexture: {fileID: 0} - m_AtlasTexture: 0 + m_ButtonTexture: {fileID: 2800000, guid: bb4439b4279219b4db937c93530893ff, type: 3} + m_AtlasTexture: 1 m_ToggleButton: 0 m_LongPressReleaseButton: 0 m_ButtonHasPressedAudio: 1 m_ZAdjustHover: -0.02 m_ZAdjustClick: 0.05 - m_HoverScale: 1.1 + m_HoverScale: 1.2 m_HoverBoxColliderGrow: 0.2 m_AddOverlay: 0 m_Command: 73 - m_CommandParam: 0 + m_CommandParam: 3 m_CommandParam2: -1 m_RequiresPopup: 0 m_CenterPopupOnButton: 0 @@ -7991,20 +8080,28 @@ MonoBehaviour: references: version: 2 RefIds: [] ---- !u!65 &2602589182038582116 +--- !u!65 &2329669131580351156 BoxCollider: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8579567244815457455} + m_GameObject: {fileID: 5978289847150237173} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 - serializedVersion: 2 - m_Size: {x: 1, y: 1, z: 0.1} + serializedVersion: 3 + m_Size: {x: 1, y: 1.0000001, z: 0.1} m_Center: {x: 0, y: 0, z: -0.01} ---- !u!1 &8644312780941313480 +--- !u!1 &6286143077313149806 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -8012,50 +8109,133 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 8425076696762416562} - - component: {fileID: 8620201613594084264} - - component: {fileID: 8530386015597152794} + - component: {fileID: 5038995524656264454} + - component: {fileID: 7928834966209772352} + - component: {fileID: 3325864671476505547} + m_Layer: 16 + m_Name: Icosa_Logo + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &5038995524656264454 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6286143077313149806} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0.278, y: 0.26200008, z: -0.01} + m_LocalScale: {x: 0.2649999, y: 0.2649999, z: 0.2649999} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1000721931266647293} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!33 &7928834966209772352 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6286143077313149806} + m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &3325864671476505547 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6286143077313149806} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 0 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: e7a4b5a3979042447af7f344f59498c7, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 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 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!1 &6559160341867036930 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 8844894437526037228} + - component: {fileID: 2123032824923807014} + - component: {fileID: 2425192678641992511} + - component: {fileID: 439132055978833134} m_Layer: 0 - m_Name: Google_Name + m_Name: Description m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!224 &8425076696762416562 +--- !u!224 &8844894437526037228 RectTransform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8644312780941313480} + m_GameObject: {fileID: 6559160341867036930} m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: -0.010000003} + m_LocalPosition: {x: 0, y: 0, z: -0.0025} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] - m_Father: {fileID: 1411852402157678472} - m_RootOrder: 2 + m_Father: {fileID: 4825048073929942150} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0, y: 0} - m_AnchorMax: {x: 0, y: 0} - m_AnchoredPosition: {x: -1.169, y: -0.477} - m_SizeDelta: {x: 1.1, y: 0.35} - m_Pivot: {x: 0, y: 0} ---- !u!23 &8620201613594084264 + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0.058} + m_SizeDelta: {x: 2.5, y: 0.7} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!23 &2123032824923807014 MeshRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8644312780941313480} + m_GameObject: {fileID: 6559160341867036930} m_Enabled: 1 m_CastShadows: 0 m_ReceiveShadows: 0 m_DynamicOccludee: 1 m_StaticShadowCaster: 0 m_MotionVectors: 1 - m_LightProbeUsage: 1 + m_LightProbeUsage: 0 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 m_RayTraceProcedural: 0 @@ -8084,13 +8264,13 @@ MeshRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!114 &8530386015597152794 +--- !u!114 &2425192678641992511 MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8644312780941313480} + m_GameObject: {fileID: 6559160341867036930} m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 9541d86e2fd84c1d9990edf0852d74ab, type: 3} @@ -8104,7 +8284,9 @@ MonoBehaviour: m_OnCullStateChanged: m_PersistentCalls: m_Calls: [] - m_text: Longnamefirstname Longnamesurname + m_text: 'Sign in to a Google account to access + + Drive and YouTube support.' m_isRightToLeft: 0 m_fontAsset: {fileID: 11400000, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} m_sharedMaterial: {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} @@ -8113,8 +8295,8 @@ MonoBehaviour: m_fontMaterials: [] m_fontColor32: serializedVersion: 2 - rgba: 4294967295 - m_fontColor: {r: 1, g: 1, b: 1, a: 1} + rgba: 4286085240 + m_fontColor: {r: 0.47058824, g: 0.47058824, b: 0.47058824, a: 1} m_enableVertexGradient: 0 m_colorMode: 3 m_fontColorGradient: @@ -8131,25 +8313,25 @@ MonoBehaviour: m_faceColor: serializedVersion: 2 rgba: 4294967295 - m_fontSize: 1.3 - m_fontSizeBase: 1.3 + m_fontSize: 1.275 + m_fontSizeBase: 1.275 m_fontWeight: 400 m_enableAutoSizing: 0 m_fontSizeMin: 18 m_fontSizeMax: 72 m_fontStyle: 0 m_HorizontalAlignment: 2 - m_VerticalAlignment: 256 + m_VerticalAlignment: 512 m_textAlignment: 65535 m_characterSpacing: 0 m_wordSpacing: 0 - m_lineSpacing: -22 + m_lineSpacing: 0 m_lineSpacingMax: 0 m_paragraphSpacing: 0 m_charWidthMaxAdj: 0 m_enableWordWrapping: 1 m_wordWrappingRatios: 0.4 - m_overflowMode: 3 + m_overflowMode: 0 m_linkedTextComponent: {fileID: 0} parentLinkedComponent: {fileID: 0} m_enableKerning: 1 @@ -8164,7 +8346,7 @@ MonoBehaviour: m_uvLineOffset: 0 m_geometrySortingOrder: 0 m_IsTextObjectScaleStatic: 0 - m_VertexBufferAutoSizeReduction: 1 + m_VertexBufferAutoSizeReduction: 0 m_useMaxVisibleDescender: 1 m_pageToDisplay: 1 m_margin: {x: 0, y: 0, z: 0, w: 0} @@ -8174,58 +8356,98 @@ MonoBehaviour: _SortingLayerID: 0 _SortingOrder: 0 m_hasFontAssetChanged: 0 - m_renderer: {fileID: 8620201613594084264} + m_renderer: {fileID: 2123032824923807014} m_maskType: 0 ---- !u!1 &8644332586413500038 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 8645625732761162234} - - component: {fileID: 8610995069649507040} - - component: {fileID: 8621276525763300312} - m_Layer: 16 - m_Name: Google_ProfilePhoto - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &8645625732761162234 -Transform: +--- !u!114 &439132055978833134 +MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8644332586413500038} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: -0.621, y: 0.11, z: -0.010000025} - m_LocalScale: {x: 0.4, y: 0.4, z: 0.4} + m_GameObject: {fileID: 6559160341867036930} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 69beb381e244f92449b8c4cf954630e9, type: 3} + m_Name: + m_EditorClassIdentifier: + m_TrackedObjects: + - rid: 3215294302546034852 + references: + version: 2 + RefIds: + - rid: 3215294302546034852 + type: {class: TrackedUGuiGraphic, ns: UnityEngine.Localization.PropertyVariants.TrackedObjects, + asm: Unity.Localization} + data: + m_Target: {fileID: 2425192678641992511} + m_TrackedProperties: + items: + - rid: 3215294302546034853 + m_UpdateType: 0 + - rid: 3215294302546034853 + type: {class: LocalizedStringProperty, ns: UnityEngine.Localization.PropertyVariants.TrackedProperties, + asm: Unity.Localization} + data: + m_Localized: + m_TableReference: + m_TableCollectionName: GUID:c84355079ab3f3e4f8f3812258805f86 + m_TableEntryReference: + m_KeyId: 76138083292602368 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_PropertyPath: m_text +--- !u!1 &6569154546886767970 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 6952797202003472198} + - component: {fileID: 3857003002993330428} + - component: {fileID: 5268851330295692068} + - component: {fileID: 4382059402420719972} + - component: {fileID: 3651181850301530278} + m_Layer: 16 + m_Name: Google_Info + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &6952797202003472198 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6569154546886767970} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: -0.213, y: 0.2620001, z: -0.025} + m_LocalScale: {x: 0.2, y: 0.2, z: 0.2} m_ConstrainProportionsScale: 0 - m_Children: - - {fileID: 8645625732756982244} - - {fileID: 3135609562369966535} - m_Father: {fileID: 1411852402157678472} - m_RootOrder: 1 + m_Children: [] + m_Father: {fileID: 1432546188030660464} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!33 &8610995069649507040 +--- !u!33 &3857003002993330428 MeshFilter: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8644332586413500038} + m_GameObject: {fileID: 6569154546886767970} m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} ---- !u!23 &8621276525763300312 +--- !u!23 &5268851330295692068 MeshRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8644332586413500038} + m_GameObject: {fileID: 6569154546886767970} m_Enabled: 1 m_CastShadows: 0 m_ReceiveShadows: 0 @@ -8239,7 +8461,7 @@ MeshRenderer: m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 2100000, guid: da7f0d43a22e3f24bbc517466728866f, type: 2} + - {fileID: 2100000, guid: 3c8ca511828182747a0b79564892ec57, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 @@ -8261,7 +8483,107 @@ MeshRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!1 &8644332586423700726 +--- !u!114 &4382059402420719972 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6569154546886767970} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fc12adcafa62a22458e635d2ee7e78b5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_DescriptionType: -1 + m_DescriptionYOffset: 0 + m_DescriptionText: + m_LocalizedDescription: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_DescriptionTextExtra: + m_LocalizedDescriptionExtra: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_DescriptionActivateSpeed: 12 + m_DescriptionZScale: 1 + m_ButtonTexture: {fileID: 2800000, guid: bb4439b4279219b4db937c93530893ff, type: 3} + m_AtlasTexture: 1 + m_ToggleButton: 0 + m_LongPressReleaseButton: 0 + m_ButtonHasPressedAudio: 1 + m_ZAdjustHover: -0.02 + m_ZAdjustClick: 0.05 + m_HoverScale: 1.2 + m_HoverBoxColliderGrow: 0.2 + m_AddOverlay: 0 + m_Command: 73 + m_CommandParam: 1 + m_CommandParam2: -1 + m_RequiresPopup: 0 + m_CenterPopupOnButton: 0 + m_PopupOffset: {x: 0, y: 0, z: 0} + m_PopupText: + m_LocalizedPopup: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_ToggleOnDescription: + m_LocalizedToggleOnDescription: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_ToggleOnTexture: {fileID: 0} + m_AllowUnavailable: 0 + m_LinkedUIObject: {fileID: 0} + m_CommandIgnored: 0 + references: + version: 2 + RefIds: [] +--- !u!65 &3651181850301530278 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6569154546886767970} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Size: {x: 1, y: 1.0000001, z: 0.1} + m_Center: {x: 0, y: 0, z: -0.01} +--- !u!1 &6655431747887542890 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -8269,60 +8591,56 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 8645625732756982244} - - component: {fileID: 8610995080555659526} - - component: {fileID: 8621276525021700672} + - component: {fileID: 277837882360728660} + - component: {fileID: 3967617528463584047} + - component: {fileID: 3967593321760830211} m_Layer: 16 - m_Name: PhotoBGW + m_Name: Google_Text m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!4 &8645625732756982244 -Transform: +--- !u!224 &277837882360728660 +RectTransform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8644332586423700726} + m_GameObject: {fileID: 6655431747887542890} m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0.0022857143} - m_LocalScale: {x: 1.1, y: 1.1, z: 1.1} + m_LocalPosition: {x: 0, y: 0, z: -0.01} + m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] - m_Father: {fileID: 8645625732761162234} - m_RootOrder: 0 + m_Father: {fileID: 1432546188030660464} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!33 &8610995080555659526 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8644332586423700726} - m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} ---- !u!23 &8621276525021700672 + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: -0.8228, y: 0.3524501} + m_SizeDelta: {x: 0.34, y: 0.17} + m_Pivot: {x: 0, y: 1} +--- !u!23 &3967617528463584047 MeshRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8644332586423700726} + m_GameObject: {fileID: 6655431747887542890} m_Enabled: 1 m_CastShadows: 0 m_ReceiveShadows: 0 m_DynamicOccludee: 1 m_StaticShadowCaster: 0 m_MotionVectors: 1 - m_LightProbeUsage: 0 + m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 2100000, guid: 0c298b4a41e7c5b4daf56d8987a83788, type: 2} + - {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 @@ -8334,7 +8652,7 @@ MeshRenderer: m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 - m_StitchLightmapSeams: 0 + m_StitchLightmapSeams: 1 m_SelectedEditorRenderState: 3 m_MinimumChartSize: 4 m_AutoUVMaxDistance: 0.5 @@ -8344,68 +8662,162 @@ MeshRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!1 &8644332587409793350 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 8645625740661137770} - - component: {fileID: 8610995081492312010} - - component: {fileID: 8621276525838995664} - m_Layer: 16 - m_Name: PopupBorder - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &8645625740661137770 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8644332587409793350} - m_LocalRotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071067} - m_LocalPosition: {x: -0, y: 0, z: 0} - m_LocalScale: {x: 100, y: 100, z: 100} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 8645625735778197046} - m_RootOrder: 1 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!33 &8610995081492312010 -MeshFilter: +--- !u!114 &3967593321760830211 +MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8644332587409793350} - m_Mesh: {fileID: 4300000, guid: 3efe5b86b55995545a231ce66a53b402, type: 3} ---- !u!23 &8621276525838995664 + m_GameObject: {fileID: 6655431747887542890} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 9541d86e2fd84c1d9990edf0852d74ab, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_text: Google + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} + m_sharedMaterial: {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4294967295 + m_fontColor: {r: 1, g: 1, b: 1, a: 1} + m_enableVertexGradient: 0 + m_colorMode: 3 + m_fontColorGradient: + topLeft: {r: 1, g: 1, b: 1, a: 1} + topRight: {r: 1, g: 1, b: 1, a: 1} + bottomLeft: {r: 1, g: 1, b: 1, a: 1} + bottomRight: {r: 1, g: 1, b: 1, a: 1} + m_fontColorGradientPreset: {fileID: 0} + m_spriteAsset: {fileID: 0} + m_tintAllSprites: 0 + m_StyleSheet: {fileID: 0} + m_TextStyleHashCode: -1183493901 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_fontSize: 1.35 + m_fontSizeBase: 1.35 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_HorizontalAlignment: 1 + m_VerticalAlignment: 256 + m_textAlignment: 65535 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_enableWordWrapping: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 0 + m_isCullingEnabled: 0 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_IsTextObjectScaleStatic: 0 + m_VertexBufferAutoSizeReduction: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + _SortingLayer: 0 + _SortingLayerID: 0 + _SortingOrder: 0 + m_hasFontAssetChanged: 0 + m_renderer: {fileID: 3967617528463584047} + m_maskType: 0 +--- !u!1 &6696247793707346302 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 3716870166160541890} + - component: {fileID: 1778902779340506197} + - component: {fileID: 596356743151083422} + - component: {fileID: 4454298294767258161} + - component: {fileID: 4808408806908219571} + m_Layer: 16 + m_Name: Icosa_SignOut + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &3716870166160541890 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6696247793707346302} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 1.041, y: 0.247, z: -0.02499998} + m_LocalScale: {x: 0.25, y: 0.24999991, z: 0.2499999} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 8994260351568061772} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!33 &1778902779340506197 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6696247793707346302} + m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &596356743151083422 MeshRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8644332587409793350} + m_GameObject: {fileID: 6696247793707346302} m_Enabled: 1 m_CastShadows: 0 m_ReceiveShadows: 0 m_DynamicOccludee: 1 m_StaticShadowCaster: 0 m_MotionVectors: 1 - m_LightProbeUsage: 1 + m_LightProbeUsage: 0 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 2100000, guid: 77dd4ff8b1158a84397aba783cd0af05, type: 2} + - {fileID: 2100000, guid: 3c8ca511828182747a0b79564892ec57, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 @@ -8427,7 +8839,107 @@ MeshRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!1 &8644332587479430734 +--- !u!114 &4454298294767258161 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6696247793707346302} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fc12adcafa62a22458e635d2ee7e78b5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_DescriptionType: 0 + m_DescriptionYOffset: 0 + m_DescriptionText: POPUP_ACCOUNTS_SIGNOUT_BUTTON_DESCRIPTION + m_LocalizedDescription: + m_TableReference: + m_TableCollectionName: GUID:c84355079ab3f3e4f8f3812258805f86 + m_TableEntryReference: + m_KeyId: 15522362785837056 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_DescriptionTextExtra: + m_LocalizedDescriptionExtra: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_DescriptionActivateSpeed: 12 + m_DescriptionZScale: 1 + m_ButtonTexture: {fileID: 2800000, guid: 42f600d7b08f5514ebdcf4604e0cfa6c, type: 3} + m_AtlasTexture: 1 + m_ToggleButton: 0 + m_LongPressReleaseButton: 0 + m_ButtonHasPressedAudio: 1 + m_ZAdjustHover: -0.02 + m_ZAdjustClick: 0.05 + m_HoverScale: 1.1 + m_HoverBoxColliderGrow: 0.2 + m_AddOverlay: 0 + m_Command: 98 + m_CommandParam: 3 + m_CommandParam2: -1 + m_RequiresPopup: 0 + m_CenterPopupOnButton: 0 + m_PopupOffset: {x: 0, y: 0, z: 0} + m_PopupText: + m_LocalizedPopup: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_ToggleOnDescription: + m_LocalizedToggleOnDescription: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_ToggleOnTexture: {fileID: 0} + m_AllowUnavailable: 0 + m_LinkedUIObject: {fileID: 0} + m_CommandIgnored: 1 + references: + version: 2 + RefIds: [] +--- !u!65 &4808408806908219571 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6696247793707346302} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Size: {x: 1, y: 1.0000001, z: 0.1} + m_Center: {x: 0, y: 0, z: -0.01} +--- !u!1 &6877995767082855847 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -8435,206 +8947,46 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 8645625734765961102} - - component: {fileID: 8529915923179660036} - - component: {fileID: 8580401944159525890} - - component: {fileID: 8533537593755566908} + - component: {fileID: 3554585349599419749} + - component: {fileID: 2124419336652034620} + - component: {fileID: 1855359805432446158} m_Layer: 16 - m_Name: PopUpWindow_Accounts + m_Name: Sketchfab_BackPlate m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!4 &8645625734765961102 +--- !u!4 &3554585349599419749 Transform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8644332587479430734} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 3, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} + m_GameObject: {fileID: 6877995767082855847} + serializedVersion: 2 + m_LocalRotation: {x: -0.7071068, y: -0, z: -0, w: 0.7071067} + m_LocalPosition: {x: 0.53499997, y: 0.2550001, z: -0.005} + m_LocalScale: {x: 32, y: 32, z: 20} m_ConstrainProportionsScale: 0 - m_Children: - - {fileID: 8645625735416266758} - - {fileID: 8645625734681381188} - - {fileID: 4825048073929942150} - - {fileID: 3576301794080265196} - - {fileID: 3457603883277620212} - - {fileID: 1766577842652504206} - - {fileID: 8645625735778197046} - m_Father: {fileID: 0} - m_RootOrder: 0 + m_Children: [] + m_Father: {fileID: 534589999851858800} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!114 &8529915923179660036 -MonoBehaviour: +--- !u!33 &2124419336652034620 +MeshFilter: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8644332587479430734} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 3fc89a0b3103cba4a9a28c525afa2ce4, type: 3} - m_Name: - m_EditorClassIdentifier: - m_Background: {fileID: 8644332588524666284} - m_TopBorder: {fileID: 8644332587409793350} - m_BottomBorder: {fileID: 8644332587409793350} - m_WindowText: {fileID: 2543170560323612900} - m_CharacterWidth: 0.075 - m_SubtitleCharacterWidth: 0.05625 - m_ButtonWidth: 0.5 - m_BaseButtonOffset: {x: 0, y: 0, z: 0} - m_ReticleBounds: {x: 1.6, y: 1.4, z: -0.35} - m_PopUpForwardOffset: -0.25 - m_AutoPlaceButtons: [] - m_TransitionDuration: 0.1 - m_OpenDelay: 0 - m_Persistent: 0 - m_AudioOnOpen: 1 - m_BlockUndoRedo: 0 - m_IsLongPressPopUp: 0 - m_OrderedPageButtons: [] - m_PrevButton: {fileID: 0} - m_NextButton: {fileID: 0} - m_ColorTransitionDuration: 0 - m_GoogleSignedInElements: {fileID: 7292193688806996409} - m_GoogleSignedOutElements: {fileID: 8372598602804526943} - m_GoogleConfirmSignOutElements: {fileID: 9078849995330061814} - m_SketchfabSignedInElements: {fileID: 5866976969575595662} - m_SketchfabSignedOutElements: {fileID: 7620355729290749329} - m_SketchfabConfirmSignOutElements: {fileID: 5649685825589421528} - m_GooglePhoto: {fileID: 8621276525763300312} - m_SketchfabPhoto: {fileID: 6282619306390002852} - m_GoogleNameText: {fileID: 8530386015597152794} - m_SketchfabNameText: {fileID: 3509174102411407934} - m_GenericPhoto: {fileID: 2800000, guid: edd2e08d6f610b840828462609546014, type: 3} - m_Accounts: {fileID: 8644332589018115638} - m_TakeOffHeadset: {fileID: 8644332588631379036} - m_GoogleInfoElements: {fileID: 8025577052483214110} - m_DriveInfoElements: {fileID: 5048206632594256402} - m_SketchfabInfoElements: {fileID: 2181120061148835783} - m_UnavailableElements: {fileID: 8374217926999613278} - m_DriveSyncEnabledElements: {fileID: 3439436514154816488} - m_DriveSyncDisabledElements: {fileID: 8663098325165672148} - m_DriveFullElements: {fileID: 5684969559238275584} - m_DriveSyncIconEnabled: {fileID: 5921053250823053932} - m_DriveSyncIconDisabled: {fileID: 4316944982740412120} - m_DriveSyncIconDriveFull: {fileID: 2727968127303647375} - m_BackupCompleteElements: {fileID: 3102330576168079932} - m_BackingUpElements: {fileID: 1118210038496079559} - m_BackingUpProgress: {fileID: 554234529220568430} - m_ConfirmLoginElements: {fileID: 0} - m_SaveAndProceedButton: {fileID: 0} ---- !u!65 &8580401944159525890 -BoxCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8644332587479430734} - m_Material: {fileID: 0} - m_IsTrigger: 0 - m_Enabled: 1 - serializedVersion: 2 - m_Size: {x: 2.6, y: 1.6, z: 0.01} - m_Center: {x: 0.05, y: -0.05, z: -0.01} ---- !u!114 &8533537593755566908 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8644332587479430734} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 739d5b1996234d64992a2ae60c3723e9, type: 3} - m_Name: - m_EditorClassIdentifier: ---- !u!1 &8644332587709734578 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 8645625735778197046} - m_Layer: 16 - m_Name: ProfilePopupMesh - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &8645625735778197046 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8644332587709734578} - 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_ConstrainProportionsScale: 0 - m_Children: - - {fileID: 8645625733637814676} - - {fileID: 8645625740661137770} - m_Father: {fileID: 8645625734765961102} - m_RootOrder: 6 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &8644332588524666284 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 8645625733637814676} - - component: {fileID: 8610995081988753086} - - component: {fileID: 8621276526632499898} - m_Layer: 16 - m_Name: PopupBg - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &8645625733637814676 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8644332588524666284} - m_LocalRotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071067} - m_LocalPosition: {x: -0, y: 0, z: 0} - m_LocalScale: {x: 100, y: 100, z: 100} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 8645625735778197046} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!33 &8610995081988753086 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8644332588524666284} + m_GameObject: {fileID: 6877995767082855847} m_Mesh: {fileID: 4300002, guid: 3efe5b86b55995545a231ce66a53b402, type: 3} ---- !u!23 &8621276526632499898 +--- !u!23 &1855359805432446158 MeshRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8644332588524666284} + m_GameObject: {fileID: 6877995767082855847} m_Enabled: 1 m_CastShadows: 0 m_ReceiveShadows: 0 @@ -8648,7 +9000,7 @@ MeshRenderer: m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 2100000, guid: db0305ff9081c3b448ac79e85d26e5d4, type: 2} + - {fileID: 2100000, guid: 8fe8230ee7ae32a4eb7fe6d5df34ebd4, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 @@ -8670,41 +9022,7 @@ MeshRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!1 &8644332588631379036 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 8645625734681381188} - m_Layer: 16 - m_Name: RemoveHeadsetElements - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 0 ---- !u!4 &8645625734681381188 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8644332588631379036} - 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_ConstrainProportionsScale: 0 - m_Children: - - {fileID: 1799102450530444095} - - {fileID: 8645625734146380956} - - {fileID: 8645625735159627316} - m_Father: {fileID: 8645625734765961102} - m_RootOrder: 1 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &8644332588836208674 +--- !u!1 &6896021414389893206 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -8712,51 +9030,49 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 1799102450530444095} - - component: {fileID: 8621276525058679400} - - component: {fileID: 5265230356848354045} - - component: {fileID: 6723664597259726558} + - component: {fileID: 2434770951962534735} + - component: {fileID: 2805088410587308415} + - component: {fileID: 6196538126404319155} m_Layer: 0 - m_Name: TakeOffHeadset + m_Name: Icosa_Name m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!224 &1799102450530444095 +--- !u!224 &2434770951962534735 RectTransform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8644332588836208674} + m_GameObject: {fileID: 6896021414389893206} m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: -0.0025} + m_LocalPosition: {x: 0, y: 0, z: -0.010000003} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] - m_Father: {fileID: 8645625734681381188} - m_RootOrder: 0 + m_Father: {fileID: 8994260351568061772} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0.5, y: 0.5} - m_AnchorMax: {x: 0.5, y: 0.5} - m_AnchoredPosition: {x: 0, y: 0.55} - m_SizeDelta: {x: 20, y: 5} - m_Pivot: {x: 0.5, y: 0.5} ---- !u!23 &8621276525058679400 + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0.059, y: -0.477} + m_SizeDelta: {x: 1.1, y: 0.35} + m_Pivot: {x: 0, y: 0} +--- !u!23 &2805088410587308415 MeshRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8644332588836208674} + m_GameObject: {fileID: 6896021414389893206} m_Enabled: 1 m_CastShadows: 0 m_ReceiveShadows: 0 m_DynamicOccludee: 1 m_StaticShadowCaster: 0 m_MotionVectors: 1 - m_LightProbeUsage: 0 + m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 m_RayTraceProcedural: 0 @@ -8785,13 +9101,13 @@ MeshRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!114 &5265230356848354045 +--- !u!114 &6196538126404319155 MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8644332588836208674} + m_GameObject: {fileID: 6896021414389893206} m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 9541d86e2fd84c1d9990edf0852d74ab, type: 3} @@ -8805,7 +9121,7 @@ MonoBehaviour: m_OnCullStateChanged: m_PersistentCalls: m_Calls: [] - m_text: Take Off Headset + m_text: Longnamefirstname Longnamesurname m_isRightToLeft: 0 m_fontAsset: {fileID: 11400000, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} m_sharedMaterial: {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} @@ -8832,25 +9148,25 @@ MonoBehaviour: m_faceColor: serializedVersion: 2 rgba: 4294967295 - m_fontSize: 1.91 - m_fontSizeBase: 1.91 + m_fontSize: 1.3 + m_fontSizeBase: 1.3 m_fontWeight: 400 m_enableAutoSizing: 0 m_fontSizeMin: 18 m_fontSizeMax: 72 m_fontStyle: 0 m_HorizontalAlignment: 2 - m_VerticalAlignment: 512 + m_VerticalAlignment: 256 m_textAlignment: 65535 m_characterSpacing: 0 m_wordSpacing: 0 - m_lineSpacing: 0 + m_lineSpacing: -22 m_lineSpacingMax: 0 m_paragraphSpacing: 0 m_charWidthMaxAdj: 0 m_enableWordWrapping: 1 m_wordWrappingRatios: 0.4 - m_overflowMode: 0 + m_overflowMode: 3 m_linkedTextComponent: {fileID: 0} parentLinkedComponent: {fileID: 0} m_enableKerning: 1 @@ -8865,7 +9181,7 @@ MonoBehaviour: m_uvLineOffset: 0 m_geometrySortingOrder: 0 m_IsTextObjectScaleStatic: 0 - m_VertexBufferAutoSizeReduction: 0 + m_VertexBufferAutoSizeReduction: 1 m_useMaxVisibleDescender: 1 m_pageToDisplay: 1 m_margin: {x: 0, y: 0, z: 0, w: 0} @@ -8875,84 +9191,221 @@ MonoBehaviour: _SortingLayerID: 0 _SortingOrder: 0 m_hasFontAssetChanged: 0 - m_renderer: {fileID: 8621276525058679400} + m_renderer: {fileID: 2805088410587308415} m_maskType: 0 ---- !u!114 &6723664597259726558 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8644332588836208674} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 69beb381e244f92449b8c4cf954630e9, type: 3} - m_Name: - m_EditorClassIdentifier: - m_TrackedObjects: - - rid: 3215294302546034842 - references: - version: 2 - RefIds: - - rid: 3215294302546034842 - type: {class: TrackedUGuiGraphic, ns: UnityEngine.Localization.PropertyVariants.TrackedObjects, - asm: Unity.Localization} - data: - m_Target: {fileID: 5265230356848354045} - m_TrackedProperties: - items: - - rid: 3215294302546034843 - m_UpdateType: 0 - - rid: 3215294302546034843 - type: {class: LocalizedStringProperty, ns: UnityEngine.Localization.PropertyVariants.TrackedProperties, - asm: Unity.Localization} - data: - m_Localized: - m_TableReference: - m_TableCollectionName: GUID:c84355079ab3f3e4f8f3812258805f86 - m_TableEntryReference: - m_KeyId: 76134950436921344 - m_Key: - m_FallbackState: 0 - m_WaitForCompletion: 0 - m_LocalVariables: [] - m_PropertyPath: m_text ---- !u!1 &8644332589018115638 -GameObject: +--- !u!1 &7039719445365502712 +GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 8645625735416266758} + - component: {fileID: 7505721524787016835} + - component: {fileID: 4823882021682760176} + - component: {fileID: 2425200055429802179} + - component: {fileID: 2982020382161640361} m_Layer: 16 - m_Name: ViewingAccountsElements + m_Name: Icosa_Text m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!4 &8645625735416266758 -Transform: +--- !u!224 &7505721524787016835 +RectTransform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8644332589018115638} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} + m_GameObject: {fileID: 7039719445365502712} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: -0.01} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 - m_Children: - - {fileID: 6204130650882258485} - - {fileID: 1182483975005714860} - - {fileID: 5854179938074699431} - - {fileID: 149137880941958609} - m_Father: {fileID: 8645625734765961102} - m_RootOrder: 0 + m_Children: [] + m_Father: {fileID: 1675920430848132177} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &8644332589239274156 + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0.429, y: 0.3524501} + m_SizeDelta: {x: 0.52, y: 0.2} + m_Pivot: {x: 0, y: 1} +--- !u!23 &4823882021682760176 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7039719445365502712} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + 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 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!114 &2425200055429802179 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7039719445365502712} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 9541d86e2fd84c1d9990edf0852d74ab, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_text: Sign Out? + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} + m_sharedMaterial: {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4294967295 + m_fontColor: {r: 1, g: 1, b: 1, a: 1} + m_enableVertexGradient: 0 + m_colorMode: 3 + m_fontColorGradient: + topLeft: {r: 1, g: 1, b: 1, a: 1} + topRight: {r: 1, g: 1, b: 1, a: 1} + bottomLeft: {r: 1, g: 1, b: 1, a: 1} + bottomRight: {r: 1, g: 1, b: 1, a: 1} + m_fontColorGradientPreset: {fileID: 0} + m_spriteAsset: {fileID: 0} + m_tintAllSprites: 0 + m_StyleSheet: {fileID: 0} + m_TextStyleHashCode: -1183493901 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_fontSize: 1.35 + m_fontSizeBase: 1.35 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_HorizontalAlignment: 1 + m_VerticalAlignment: 256 + m_textAlignment: 65535 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_enableWordWrapping: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 0 + m_isCullingEnabled: 0 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_IsTextObjectScaleStatic: 0 + m_VertexBufferAutoSizeReduction: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + _SortingLayer: 0 + _SortingLayerID: 0 + _SortingOrder: 0 + m_hasFontAssetChanged: 0 + m_renderer: {fileID: 4823882021682760176} + m_maskType: 0 +--- !u!114 &2982020382161640361 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7039719445365502712} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 69beb381e244f92449b8c4cf954630e9, type: 3} + m_Name: + m_EditorClassIdentifier: + m_TrackedObjects: + - rid: 8021623883140169743 + references: + version: 2 + RefIds: + - rid: 8021623883140169743 + type: {class: TrackedUGuiGraphic, ns: UnityEngine.Localization.PropertyVariants.TrackedObjects, + asm: Unity.Localization} + data: + m_Target: {fileID: 2425200055429802179} + m_TrackedProperties: + items: + - rid: 8021623883140169744 + m_UpdateType: 0 + - rid: 8021623883140169744 + type: {class: LocalizedStringProperty, ns: UnityEngine.Localization.PropertyVariants.TrackedProperties, + asm: Unity.Localization} + data: + m_Localized: + m_TableReference: + m_TableCollectionName: GUID:c84355079ab3f3e4f8f3812258805f86 + m_TableEntryReference: + m_KeyId: 15531555001511936 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_PropertyPath: m_text +--- !u!1 &7241757417913730636 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -8960,64 +9413,60 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 8645625735159627316} - - component: {fileID: 8610995070916950296} - - component: {fileID: 8621276523770920886} - - component: {fileID: 8580401943792562782} - - component: {fileID: 853645773711861975} - m_Layer: 14 - m_Name: ConfirmationButton + - component: {fileID: 2399947737502410141} + - component: {fileID: 7967378821529834859} + - component: {fileID: 1423734451789490328} + m_Layer: 16 + m_Name: Google_BackPlate m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!4 &8645625735159627316 +--- !u!4 &2399947737502410141 Transform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8644332589239274156} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: -0.434, z: -0.08} - m_LocalScale: {x: 0.6, y: 0.29999998, z: 0.29999998} + m_GameObject: {fileID: 7241757417913730636} + serializedVersion: 2 + m_LocalRotation: {x: -0.7071068, y: -0, z: -0, w: 0.7071067} + m_LocalPosition: {x: -0.622, y: 0.2550001, z: -0.005} + m_LocalScale: {x: 32, y: 32, z: 20} m_ConstrainProportionsScale: 0 - m_Children: - - {fileID: 1829480651769887961} - - {fileID: 8645625732950447588} - m_Father: {fileID: 8645625734681381188} - m_RootOrder: 2 + m_Children: [] + m_Father: {fileID: 7741920746089690377} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!33 &8610995070916950296 +--- !u!33 &7967378821529834859 MeshFilter: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8644332589239274156} - m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} ---- !u!23 &8621276523770920886 + m_GameObject: {fileID: 7241757417913730636} + m_Mesh: {fileID: 4300002, guid: 3efe5b86b55995545a231ce66a53b402, type: 3} +--- !u!23 &1423734451789490328 MeshRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8644332589239274156} - m_Enabled: 0 + m_GameObject: {fileID: 7241757417913730636} + m_Enabled: 1 m_CastShadows: 0 m_ReceiveShadows: 0 m_DynamicOccludee: 1 m_StaticShadowCaster: 0 m_MotionVectors: 1 - m_LightProbeUsage: 0 + m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 2100000, guid: 3c8ca511828182747a0b79564892ec57, type: 2} + - {fileID: 2100000, guid: 8fe8230ee7ae32a4eb7fe6d5df34ebd4, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 @@ -9039,182 +9488,43 @@ MeshRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!65 &8580401943792562782 -BoxCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8644332589239274156} - m_Material: {fileID: 0} - m_IsTrigger: 0 - m_Enabled: 1 - serializedVersion: 2 - m_Size: {x: 1, y: 1, z: 0.01} - m_Center: {x: 0, y: 0, z: -0.01} ---- !u!114 &853645773711861975 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8644332589239274156} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fc12adcafa62a22458e635d2ee7e78b5, type: 3} - m_Name: - m_EditorClassIdentifier: - m_DescriptionType: -1 - m_DescriptionYOffset: 0 - m_DescriptionText: - m_LocalizedDescription: - m_TableReference: - m_TableCollectionName: - m_TableEntryReference: - m_KeyId: 0 - m_Key: - m_FallbackState: 0 - m_WaitForCompletion: 0 - m_LocalVariables: [] - m_DescriptionTextExtra: - m_LocalizedDescriptionExtra: - m_TableReference: - m_TableCollectionName: - m_TableEntryReference: - m_KeyId: 0 - m_Key: - m_FallbackState: 0 - m_WaitForCompletion: 0 - m_LocalVariables: [] - m_DescriptionActivateSpeed: 12 - m_DescriptionZScale: 1 - m_ButtonTexture: {fileID: 0} - m_AtlasTexture: 0 - m_ToggleButton: 0 - m_LongPressReleaseButton: 0 - m_ButtonHasPressedAudio: 1 - m_ZAdjustHover: -0.02 - m_ZAdjustClick: 0.05 - m_HoverScale: 1.1 - m_HoverBoxColliderGrow: 0.2 - m_AddOverlay: 0 - m_Command: 0 - m_CommandParam: -1 - m_CommandParam2: -1 - m_RequiresPopup: 0 - m_CenterPopupOnButton: 0 - m_PopupOffset: {x: 0, y: 0, z: 0} - m_PopupText: - m_LocalizedPopup: - m_TableReference: - m_TableCollectionName: - m_TableEntryReference: - m_KeyId: 0 - m_Key: - m_FallbackState: 0 - m_WaitForCompletion: 0 - m_LocalVariables: [] - m_ToggleOnDescription: - m_LocalizedToggleOnDescription: - m_TableReference: - m_TableCollectionName: - m_TableEntryReference: - m_KeyId: 0 - m_Key: - m_FallbackState: 0 - m_WaitForCompletion: 0 - m_LocalVariables: [] - m_ToggleOnTexture: {fileID: 0} - m_AllowUnavailable: 0 - m_LinkedUIObject: {fileID: 0} - m_CommandIgnored: 0 - references: - version: 2 - RefIds: [] ---- !u!1 &8644332589642346024 -GameObject: +--- !u!1 &7292193688806996409 +GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 8645625734146380956} - - component: {fileID: 8610995080664749698} - - component: {fileID: 8621276525178098980} + - component: {fileID: 1411852402157678472} m_Layer: 16 - m_Name: Animation + m_Name: Google_SignedInElements m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!4 &8645625734146380956 +--- !u!4 &1411852402157678472 Transform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8644332589642346024} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: 0.099, z: -0.0025} - m_LocalScale: {x: 0.7, y: 0.7, z: 1} + m_GameObject: {fileID: 7292193688806996409} + serializedVersion: 2 + 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_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 8645625734681381188} - m_RootOrder: 1 + m_Children: + - {fileID: 8645625734912766616} + - {fileID: 8645625732761162234} + - {fileID: 8425076696762416562} + - {fileID: 1741904442304953456} + - {fileID: 6692607038900794975} + m_Father: {fileID: 5854179938074699431} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!33 &8610995080664749698 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8644332589642346024} - m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} ---- !u!23 &8621276525178098980 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8644332589642346024} - m_Enabled: 1 - m_CastShadows: 0 - m_ReceiveShadows: 0 - m_DynamicOccludee: 1 - m_StaticShadowCaster: 0 - m_MotionVectors: 1 - m_LightProbeUsage: 0 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RayTraceProcedural: 0 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 2100000, guid: cc3ea5371dc184af2a1640b84d45f29e, type: 2} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 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 - m_AdditionalVertexStreams: {fileID: 0} ---- !u!1 &8644332589849401822 +--- !u!1 &7389499574749059798 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -9222,60 +9532,57 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 8645625732950447588} - - component: {fileID: 8610995080173436830} - - component: {fileID: 8621276523781374462} - m_Layer: 16 - m_Name: Background + - component: {fileID: 9062749716723118463} + - component: {fileID: 5851412377445962644} + - component: {fileID: 5204209675494704913} + - component: {fileID: 495762216464883552} + m_Layer: 0 + m_Name: Title m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!4 &8645625732950447588 -Transform: +--- !u!224 &9062749716723118463 +RectTransform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8644332589849401822} + m_GameObject: {fileID: 7389499574749059798} m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0.0021666286, y: 0, z: 0} + m_LocalPosition: {x: 0, y: 0, z: -0.0025} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] - m_Father: {fileID: 8645625735159627316} - m_RootOrder: 1 + m_Father: {fileID: 1766577842652504206} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!33 &8610995080173436830 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8644332589849401822} - m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} ---- !u!23 &8621276523781374462 + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0.5} + m_SizeDelta: {x: 2.27, y: 0.3} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!23 &5851412377445962644 MeshRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8644332589849401822} + m_GameObject: {fileID: 7389499574749059798} m_Enabled: 1 m_CastShadows: 0 m_ReceiveShadows: 0 m_DynamicOccludee: 1 m_StaticShadowCaster: 0 m_MotionVectors: 1 - m_LightProbeUsage: 1 + m_LightProbeUsage: 0 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 2100000, guid: 39d7053101c6e8e4b8d692eddc65d2b2, type: 2} + - {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 @@ -9284,7 +9591,7 @@ MeshRenderer: m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 m_ReceiveGI: 1 - m_PreserveUVs: 1 + m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 m_StitchLightmapSeams: 0 @@ -9297,59 +9604,190 @@ MeshRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!1 &8644332589952109232 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 6204130650882258485} - - component: {fileID: 7331502488059647707} - - component: {fileID: 2543170560323612900} - - component: {fileID: 3707599773211769618} - m_Layer: 16 - m_Name: Title - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!224 &6204130650882258485 -RectTransform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8644332589952109232} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: -0.0025} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 8645625735416266758} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} - m_AnchorMin: {x: 0.5, y: 0.5} - m_AnchorMax: {x: 0.5, y: 0.5} - m_AnchoredPosition: {x: -1.171, y: 0.731} - m_SizeDelta: {x: 2.37, y: 0.3} - m_Pivot: {x: 0, y: 1} ---- !u!23 &7331502488059647707 -MeshRenderer: +--- !u!114 &5204209675494704913 +MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8644332589952109232} + m_GameObject: {fileID: 7389499574749059798} m_Enabled: 1 - m_CastShadows: 0 - m_ReceiveShadows: 0 - m_DynamicOccludee: 1 - m_StaticShadowCaster: 0 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 9541d86e2fd84c1d9990edf0852d74ab, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_text: Error + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} + m_sharedMaterial: {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4294967295 + m_fontColor: {r: 1, g: 1, b: 1, a: 1} + m_enableVertexGradient: 0 + m_colorMode: 3 + m_fontColorGradient: + topLeft: {r: 1, g: 1, b: 1, a: 1} + topRight: {r: 1, g: 1, b: 1, a: 1} + bottomLeft: {r: 1, g: 1, b: 1, a: 1} + bottomRight: {r: 1, g: 1, b: 1, a: 1} + m_fontColorGradientPreset: {fileID: 0} + m_spriteAsset: {fileID: 0} + m_tintAllSprites: 0 + m_StyleSheet: {fileID: 0} + m_TextStyleHashCode: -1183493901 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_fontSize: 1.915 + m_fontSizeBase: 1.915 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_HorizontalAlignment: 2 + m_VerticalAlignment: 512 + m_textAlignment: 65535 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_enableWordWrapping: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 0 + m_isCullingEnabled: 0 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_IsTextObjectScaleStatic: 0 + m_VertexBufferAutoSizeReduction: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + _SortingLayer: 0 + _SortingLayerID: 0 + _SortingOrder: 0 + m_hasFontAssetChanged: 0 + m_renderer: {fileID: 5851412377445962644} + m_maskType: 0 +--- !u!114 &495762216464883552 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7389499574749059798} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 69beb381e244f92449b8c4cf954630e9, type: 3} + m_Name: + m_EditorClassIdentifier: + m_TrackedObjects: + - rid: 3215294302546034854 + references: + version: 2 + RefIds: + - rid: 3215294302546034854 + type: {class: TrackedUGuiGraphic, ns: UnityEngine.Localization.PropertyVariants.TrackedObjects, + asm: Unity.Localization} + data: + m_Target: {fileID: 5204209675494704913} + m_TrackedProperties: + items: + - rid: 3215294302546034855 + m_UpdateType: 0 + - rid: 3215294302546034855 + type: {class: LocalizedStringProperty, ns: UnityEngine.Localization.PropertyVariants.TrackedProperties, + asm: Unity.Localization} + data: + m_Localized: + m_TableReference: + m_TableCollectionName: GUID:c84355079ab3f3e4f8f3812258805f86 + m_TableEntryReference: + m_KeyId: 147094550989828096 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_PropertyPath: m_text +--- !u!1 &7395606162817237834 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4750169147585981226} + - component: {fileID: 7886381469928682462} + - component: {fileID: 2362981489817548973} + - component: {fileID: 5340067591165246768} + m_Layer: 16 + m_Name: Got it + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &4750169147585981226 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7395606162817237834} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: -0.029333334} + m_LocalScale: {x: 2.9528668, y: 5.9057336, z: 2.9528668} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 7500850895307564819} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0.141, y: 0} + m_SizeDelta: {x: 0.25, y: 0.15} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!23 &7886381469928682462 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7395606162817237834} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 - m_LightProbeUsage: 1 + m_LightProbeUsage: 0 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 m_RayTraceProcedural: 0 @@ -9368,7 +9806,7 @@ MeshRenderer: m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 - m_StitchLightmapSeams: 1 + m_StitchLightmapSeams: 0 m_SelectedEditorRenderState: 3 m_MinimumChartSize: 4 m_AutoUVMaxDistance: 0.5 @@ -9378,13 +9816,13 @@ MeshRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!114 &2543170560323612900 +--- !u!114 &2362981489817548973 MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8644332589952109232} + m_GameObject: {fileID: 7395606162817237834} m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 9541d86e2fd84c1d9990edf0852d74ab, type: 3} @@ -9398,7 +9836,7 @@ MonoBehaviour: m_OnCullStateChanged: m_PersistentCalls: m_Calls: [] - m_text: Accounts + m_text: GOT IT m_isRightToLeft: 0 m_fontAsset: {fileID: 11400000, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} m_sharedMaterial: {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} @@ -9425,15 +9863,15 @@ MonoBehaviour: m_faceColor: serializedVersion: 2 rgba: 4294967295 - m_fontSize: 1.92 - m_fontSizeBase: 1.92 + m_fontSize: 0.64 + m_fontSizeBase: 0.64 m_fontWeight: 400 m_enableAutoSizing: 0 m_fontSizeMin: 18 m_fontSizeMax: 72 m_fontStyle: 0 - m_HorizontalAlignment: 1 - m_VerticalAlignment: 256 + m_HorizontalAlignment: 2 + m_VerticalAlignment: 512 m_textAlignment: 65535 m_characterSpacing: 0 m_wordSpacing: 0 @@ -9468,35 +9906,35 @@ MonoBehaviour: _SortingLayerID: 0 _SortingOrder: 0 m_hasFontAssetChanged: 0 - m_renderer: {fileID: 7331502488059647707} + m_renderer: {fileID: 7886381469928682462} m_maskType: 0 ---- !u!114 &3707599773211769618 +--- !u!114 &5340067591165246768 MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8644332589952109232} + m_GameObject: {fileID: 7395606162817237834} m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 69beb381e244f92449b8c4cf954630e9, type: 3} m_Name: m_EditorClassIdentifier: m_TrackedObjects: - - rid: 3215294302546034834 + - rid: 3215294302546034844 references: version: 2 RefIds: - - rid: 3215294302546034834 + - rid: 3215294302546034844 type: {class: TrackedUGuiGraphic, ns: UnityEngine.Localization.PropertyVariants.TrackedObjects, asm: Unity.Localization} data: - m_Target: {fileID: 2543170560323612900} + m_Target: {fileID: 2362981489817548973} m_TrackedProperties: items: - - rid: 3215294302546034835 + - rid: 3215294302546034845 m_UpdateType: 0 - - rid: 3215294302546034835 + - rid: 3215294302546034845 type: {class: LocalizedStringProperty, ns: UnityEngine.Localization.PropertyVariants.TrackedProperties, asm: Unity.Localization} data: @@ -9504,13 +9942,13 @@ MonoBehaviour: m_TableReference: m_TableCollectionName: GUID:c84355079ab3f3e4f8f3812258805f86 m_TableEntryReference: - m_KeyId: 76131299773440000 + m_KeyId: 76036746777255936 m_Key: m_FallbackState: 0 m_WaitForCompletion: 0 m_LocalVariables: [] m_PropertyPath: m_text ---- !u!1 &8644332590165761558 +--- !u!1 &7464697824948226506 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -9518,62 +9956,60 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 8645625734912766616} - - component: {fileID: 8610995070142662328} - - component: {fileID: 8621276526839603414} - - component: {fileID: 6538246798073148024} - - component: {fileID: 8580401943618346556} + - component: {fileID: 5753424830644711893} + - component: {fileID: 5785604700358356680} + - component: {fileID: 4813821531570180984} m_Layer: 16 - m_Name: Google_SignOut + m_Name: Sketchfab_BackPlate m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!4 &8645625734912766616 +--- !u!4 &5753424830644711893 Transform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8644332590165761558} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: -0.193, y: 0.247, z: -0.02499998} - m_LocalScale: {x: 0.25, y: 0.24999991, z: 0.2499999} + m_GameObject: {fileID: 7464697824948226506} + serializedVersion: 2 + m_LocalRotation: {x: -0.7071068, y: -0, z: -0, w: 0.7071067} + m_LocalPosition: {x: 0.621, y: -0.151, z: -0.005} + m_LocalScale: {x: 47, y: 49.999924, z: 74.2} m_ConstrainProportionsScale: 0 m_Children: [] - m_Father: {fileID: 1411852402157678472} - m_RootOrder: 0 + m_Father: {fileID: 529827201699571093} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!33 &8610995070142662328 +--- !u!33 &5785604700358356680 MeshFilter: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8644332590165761558} - m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} ---- !u!23 &8621276526839603414 + m_GameObject: {fileID: 7464697824948226506} + m_Mesh: {fileID: 4300002, guid: 3efe5b86b55995545a231ce66a53b402, type: 3} +--- !u!23 &4813821531570180984 MeshRenderer: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8644332590165761558} + m_GameObject: {fileID: 7464697824948226506} m_Enabled: 1 m_CastShadows: 0 m_ReceiveShadows: 0 m_DynamicOccludee: 1 m_StaticShadowCaster: 0 m_MotionVectors: 1 - m_LightProbeUsage: 0 + m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 2100000, guid: 3c8ca511828182747a0b79564892ec57, type: 2} + - {fileID: 2100000, guid: 8fe8230ee7ae32a4eb7fe6d5df34ebd4, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 @@ -9595,99 +10031,90 @@ MeshRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_AdditionalVertexStreams: {fileID: 0} ---- !u!114 &6538246798073148024 -MonoBehaviour: +--- !u!1 &7600327135675325717 +GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8644332590165761558} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: fc12adcafa62a22458e635d2ee7e78b5, type: 3} - m_Name: - m_EditorClassIdentifier: - m_DescriptionType: 0 - m_DescriptionYOffset: 0 - m_DescriptionText: POPUP_ACCOUNTS_SIGNOUT_BUTTON_DESCRIPTION - m_LocalizedDescription: - m_TableReference: - m_TableCollectionName: GUID:c84355079ab3f3e4f8f3812258805f86 - m_TableEntryReference: - m_KeyId: 15522362785837056 - m_Key: - m_FallbackState: 0 - m_WaitForCompletion: 0 - m_LocalVariables: [] - m_DescriptionTextExtra: - m_LocalizedDescriptionExtra: - m_TableReference: - m_TableCollectionName: - m_TableEntryReference: - m_KeyId: 0 - m_Key: - m_FallbackState: 0 - m_WaitForCompletion: 0 - m_LocalVariables: [] - m_DescriptionActivateSpeed: 12 - m_DescriptionZScale: 1 - m_ButtonTexture: {fileID: 2800000, guid: 42f600d7b08f5514ebdcf4604e0cfa6c, type: 3} - m_AtlasTexture: 1 - m_ToggleButton: 0 - m_LongPressReleaseButton: 0 - m_ButtonHasPressedAudio: 1 - m_ZAdjustHover: -0.02 - m_ZAdjustClick: 0.05 - m_HoverScale: 1.1 - m_HoverBoxColliderGrow: 0.2 - m_AddOverlay: 0 - m_Command: 98 - m_CommandParam: 1 - m_CommandParam2: -1 - m_RequiresPopup: 0 - m_CenterPopupOnButton: 0 - m_PopupOffset: {x: 0, y: 0, z: 0} - m_PopupText: - m_LocalizedPopup: - m_TableReference: - m_TableCollectionName: - m_TableEntryReference: - m_KeyId: 0 - m_Key: - m_FallbackState: 0 - m_WaitForCompletion: 0 - m_LocalVariables: [] - m_ToggleOnDescription: - m_LocalizedToggleOnDescription: - m_TableReference: - m_TableCollectionName: - m_TableEntryReference: - m_KeyId: 0 - m_Key: - m_FallbackState: 0 - m_WaitForCompletion: 0 - m_LocalVariables: [] - m_ToggleOnTexture: {fileID: 0} - m_AllowUnavailable: 0 - m_LinkedUIObject: {fileID: 0} - m_CommandIgnored: 1 - references: - version: 2 - RefIds: [] ---- !u!65 &8580401943618346556 -BoxCollider: + serializedVersion: 6 + m_Component: + - component: {fileID: 3392034205142368857} + - component: {fileID: 6946978540861440256} + - component: {fileID: 2741931446377032717} + m_Layer: 16 + m_Name: PhotoBGW + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &3392034205142368857 +Transform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8644332590165761558} - m_Material: {fileID: 0} - m_IsTrigger: 0 - m_Enabled: 1 + m_GameObject: {fileID: 7600327135675325717} serializedVersion: 2 - m_Size: {x: 1, y: 1.0000001, z: 0.1} - m_Center: {x: 0, y: 0, z: -0.01} ---- !u!1 &9067465071141378777 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0.0022857143} + m_LocalScale: {x: 1.1, y: 1.1, z: 1.1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 5621771514230647440} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!33 &6946978540861440256 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7600327135675325717} + m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &2741931446377032717 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7600327135675325717} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 0 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 0c298b4a41e7c5b4daf56d8987a83788, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 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 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!1 &7620355729290749329 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -9695,33 +10122,35 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 149137880941958609} + - component: {fileID: 534589999851858800} m_Layer: 16 - m_Name: Sketchfab + m_Name: Sketchfab_SignedOutElements m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!4 &149137880941958609 +--- !u!4 &534589999851858800 Transform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 9067465071141378777} + m_GameObject: {fileID: 7620355729290749329} + serializedVersion: 2 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_ConstrainProportionsScale: 0 m_Children: - - {fileID: 529827201699571093} - - {fileID: 534589999851858800} - - {fileID: 6423827612944397798} - m_Father: {fileID: 8645625735416266758} - m_RootOrder: 3 + - {fileID: 3554585349599419749} + - {fileID: 4946117081540083272} + - {fileID: 5383840309452991305} + - {fileID: 4700142148089133932} + - {fileID: 181638217984195686} + m_Father: {fileID: 149137880941958609} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &9078849995330061814 +--- !u!1 &7725770829448276136 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -9729,38 +10158,4840 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 7741920746089690377} + - component: {fileID: 5383840309452991305} + - component: {fileID: 1591778397208625653} + - component: {fileID: 3852620365131538827} m_Layer: 16 - m_Name: Google_ConfirmSignOutElements + m_Name: Sketchfab_Text m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!4 &7741920746089690377 -Transform: +--- !u!224 &5383840309452991305 +RectTransform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 9078849995330061814} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} + m_GameObject: {fileID: 7725770829448276136} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: -0.01} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 - m_Children: - - {fileID: 2399947737502410141} - - {fileID: 6112888683899395240} - - {fileID: 5446221535905318599} - - {fileID: 4590447671262214820} - m_Father: {fileID: 5854179938074699431} - m_RootOrder: 2 + m_Children: [] + m_Father: {fileID: 534589999851858800} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0.428, y: 0.3524501} + m_SizeDelta: {x: 20, y: 5} + m_Pivot: {x: 0, y: 1} +--- !u!23 &1591778397208625653 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7725770829448276136} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + 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 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!114 &3852620365131538827 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7725770829448276136} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 9541d86e2fd84c1d9990edf0852d74ab, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_text: Sketchfab + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} + m_sharedMaterial: {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4294967295 + m_fontColor: {r: 1, g: 1, b: 1, a: 1} + m_enableVertexGradient: 0 + m_colorMode: 3 + m_fontColorGradient: + topLeft: {r: 1, g: 1, b: 1, a: 1} + topRight: {r: 1, g: 1, b: 1, a: 1} + bottomLeft: {r: 1, g: 1, b: 1, a: 1} + bottomRight: {r: 1, g: 1, b: 1, a: 1} + m_fontColorGradientPreset: {fileID: 0} + m_spriteAsset: {fileID: 0} + m_tintAllSprites: 0 + m_StyleSheet: {fileID: 0} + m_TextStyleHashCode: -1183493901 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_fontSize: 1.35 + m_fontSizeBase: 1.35 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_HorizontalAlignment: 1 + m_VerticalAlignment: 256 + m_textAlignment: 65535 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_enableWordWrapping: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 0 + m_isCullingEnabled: 0 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_IsTextObjectScaleStatic: 0 + m_VertexBufferAutoSizeReduction: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + _SortingLayer: 0 + _SortingLayerID: 0 + _SortingOrder: 0 + m_hasFontAssetChanged: 0 + m_renderer: {fileID: 1591778397208625653} + m_maskType: 0 +--- !u!1 &7739595941385861960 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 8639010961277564811} + - component: {fileID: 751210734990785936} + - component: {fileID: 1903627422300433447} + m_Layer: 16 + m_Name: PhotoBGW + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &8639010961277564811 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7739595941385861960} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0.0022857143} + m_LocalScale: {x: 1.1, y: 1.1, z: 1.1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 9214833072643761372} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!33 &751210734990785936 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7739595941385861960} + m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &1903627422300433447 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7739595941385861960} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 0 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 0c298b4a41e7c5b4daf56d8987a83788, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 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 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!1 &7769069705588964375 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 8304354692682796117} + - component: {fileID: 6573425907134553916} + - component: {fileID: 8994872189112949042} + - component: {fileID: 8588625045096316444} + m_Layer: 0 + m_Name: Title + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &8304354692682796117 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7769069705588964375} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: -0.0025} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 6373137851377895237} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0.5} + m_SizeDelta: {x: 2.27, y: 0.3} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!23 &6573425907134553916 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7769069705588964375} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 0 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 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 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!114 &8994872189112949042 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7769069705588964375} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 9541d86e2fd84c1d9990edf0852d74ab, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_text: Share to Icosa + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} + m_sharedMaterial: {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4294967295 + m_fontColor: {r: 1, g: 1, b: 1, a: 1} + m_enableVertexGradient: 0 + m_colorMode: 3 + m_fontColorGradient: + topLeft: {r: 1, g: 1, b: 1, a: 1} + topRight: {r: 1, g: 1, b: 1, a: 1} + bottomLeft: {r: 1, g: 1, b: 1, a: 1} + bottomRight: {r: 1, g: 1, b: 1, a: 1} + m_fontColorGradientPreset: {fileID: 0} + m_spriteAsset: {fileID: 0} + m_tintAllSprites: 0 + m_StyleSheet: {fileID: 0} + m_TextStyleHashCode: -1183493901 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_fontSize: 1.915 + m_fontSizeBase: 1.915 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_HorizontalAlignment: 2 + m_VerticalAlignment: 512 + m_textAlignment: 65535 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_enableWordWrapping: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 0 + m_isCullingEnabled: 0 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_IsTextObjectScaleStatic: 0 + m_VertexBufferAutoSizeReduction: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + _SortingLayer: 0 + _SortingLayerID: 0 + _SortingOrder: 0 + m_hasFontAssetChanged: 0 + m_renderer: {fileID: 6573425907134553916} + m_maskType: 0 +--- !u!114 &8588625045096316444 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7769069705588964375} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 69beb381e244f92449b8c4cf954630e9, type: 3} + m_Name: + m_EditorClassIdentifier: + m_TrackedObjects: + - rid: 3215294302546034854 + references: + version: 2 + RefIds: + - rid: 3215294302546034854 + type: {class: TrackedUGuiGraphic, ns: UnityEngine.Localization.PropertyVariants.TrackedObjects, + asm: Unity.Localization} + data: + m_Target: {fileID: 8994872189112949042} + m_TrackedProperties: + items: + - rid: 3215294302546034855 + m_UpdateType: 0 + - rid: 3215294302546034855 + type: {class: LocalizedStringProperty, ns: UnityEngine.Localization.PropertyVariants.TrackedProperties, + asm: Unity.Localization} + data: + m_Localized: + m_TableReference: + m_TableCollectionName: GUID:c84355079ab3f3e4f8f3812258805f86 + m_TableEntryReference: + m_KeyId: 164911966586494976 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_PropertyPath: m_text +--- !u!1 &7844204848832429112 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 8006143071345660080} + - component: {fileID: 8207801876785030697} + - component: {fileID: 5143970747722748072} + m_Layer: 16 + m_Name: Background + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &8006143071345660080 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7844204848832429112} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0.0021666286, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 7338107887349877872} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!33 &8207801876785030697 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7844204848832429112} + m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &5143970747722748072 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7844204848832429112} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 39d7053101c6e8e4b8d692eddc65d2b2, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 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 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!1 &7987582482775903940 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 8146115410073256732} + - component: {fileID: 1622672940972688331} + - component: {fileID: 6831363116423794729} + m_Layer: 16 + m_Name: Sketchfab_Logo + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &8146115410073256732 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7987582482775903940} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0.37, y: -0.324, z: -0.025} + m_LocalScale: {x: 0.4, y: 0.4, z: 0.4} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 9214833072643761372} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!33 &1622672940972688331 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7987582482775903940} + m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &6831363116423794729 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7987582482775903940} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 0 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: e7a4b5a3979042447af7f344f59498c7, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 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 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!1 &8025577052483214110 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4825048073929942150} + m_Layer: 16 + m_Name: GoogleInfoElements + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 0 +--- !u!4 &4825048073929942150 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8025577052483214110} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0.13499999, z: 0} + m_LocalScale: {x: 0.85, y: 0.8500001, z: 0.8500001} + m_ConstrainProportionsScale: 1 + m_Children: + - {fileID: 9209058213459650767} + - {fileID: 8844894437526037228} + - {fileID: 6721629502030059466} + m_Father: {fileID: 8645625734765961102} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &8071707898958835644 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 8121802616684643442} + - component: {fileID: 2977604093551169432} + - component: {fileID: 4846230962093696328} + - component: {fileID: 3099629273452162997} + - component: {fileID: 4597543144213941713} + m_Layer: 16 + m_Name: Button_ClosePopup + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &8121802616684643442 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8071707898958835644} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 1.102, y: -0.576, z: -0.054} + m_LocalScale: {x: 0.29999995, y: 0.29999998, z: 0.29999998} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 7015353133639046746} + - {fileID: 7380447630107943821} + m_Father: {fileID: 282387885870267606} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!33 &2977604093551169432 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8071707898958835644} + m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &4846230962093696328 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8071707898958835644} + m_Enabled: 0 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 0 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 3c8ca511828182747a0b79564892ec57, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 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 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!65 &3099629273452162997 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8071707898958835644} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Size: {x: 1.0000001, y: 1, z: 0.01} + m_Center: {x: 0, y: 0, z: -0.01} +--- !u!114 &4597543144213941713 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8071707898958835644} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 07f172f1096366841bb9362060bb0095, type: 3} + m_Name: + m_EditorClassIdentifier: + m_DescriptionType: 0 + m_DescriptionYOffset: 0 + m_DescriptionText: Close + m_LocalizedDescription: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_DescriptionTextExtra: + m_LocalizedDescriptionExtra: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_DescriptionActivateSpeed: 12 + m_DescriptionZScale: 1 + m_ButtonTexture: {fileID: 0} + m_AtlasTexture: 1 + m_ToggleButton: 0 + m_LongPressReleaseButton: 0 + m_ButtonHasPressedAudio: 1 + m_ZAdjustHover: -0.02 + m_ZAdjustClick: 0.03 + m_HoverScale: 1.1 + m_HoverBoxColliderGrow: 0.2 + m_AddOverlay: 0 + m_Action: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 8529915923179660036} + m_TargetAssemblyTypeName: TiltBrush.ProfilePopUpWindow, Assembly-CSharp + m_MethodName: HideIcosaLogin + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 + references: + version: 2 + RefIds: [] +--- !u!1 &8156563521135199732 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 3376029733079660750} + - component: {fileID: 4750026522078451160} + - component: {fileID: 8973140315319083013} + - component: {fileID: 1977399286951791455} + m_Layer: 16 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &3376029733079660750 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8156563521135199732} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: -0.009999992} + m_LocalScale: {x: 4, y: 4, z: 2.857143} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 181638217984195686} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: -0.202, y: 0} + m_SizeDelta: {x: 0.3, y: 0.15} + m_Pivot: {x: 0, y: 0.5} +--- !u!23 &4750026522078451160 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8156563521135199732} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + 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 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!114 &8973140315319083013 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8156563521135199732} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 9541d86e2fd84c1d9990edf0852d74ab, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_text: SIGN IN + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} + m_sharedMaterial: {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4294967295 + m_fontColor: {r: 1, g: 1, b: 1, a: 1} + m_enableVertexGradient: 0 + m_colorMode: 3 + m_fontColorGradient: + topLeft: {r: 1, g: 1, b: 1, a: 1} + topRight: {r: 1, g: 1, b: 1, a: 1} + bottomLeft: {r: 1, g: 1, b: 1, a: 1} + bottomRight: {r: 1, g: 1, b: 1, a: 1} + m_fontColorGradientPreset: {fileID: 0} + m_spriteAsset: {fileID: 0} + m_tintAllSprites: 0 + m_StyleSheet: {fileID: 0} + m_TextStyleHashCode: -1183493901 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_fontSize: 0.86 + m_fontSizeBase: 0.86 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_HorizontalAlignment: 1 + m_VerticalAlignment: 512 + m_textAlignment: 65535 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_enableWordWrapping: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 0 + m_isCullingEnabled: 0 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_IsTextObjectScaleStatic: 0 + m_VertexBufferAutoSizeReduction: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + _SortingLayer: 0 + _SortingLayerID: 0 + _SortingOrder: 0 + m_hasFontAssetChanged: 0 + m_renderer: {fileID: 4750026522078451160} + m_maskType: 0 +--- !u!114 &1977399286951791455 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8156563521135199732} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 69beb381e244f92449b8c4cf954630e9, type: 3} + m_Name: + m_EditorClassIdentifier: + m_TrackedObjects: + - rid: 3215294302546034848 + references: + version: 2 + RefIds: + - rid: 3215294302546034848 + type: {class: TrackedUGuiGraphic, ns: UnityEngine.Localization.PropertyVariants.TrackedObjects, + asm: Unity.Localization} + data: + m_Target: {fileID: 8973140315319083013} + m_TrackedProperties: + items: + - rid: 3215294302546034849 + m_UpdateType: 0 + - rid: 3215294302546034849 + type: {class: LocalizedStringProperty, ns: UnityEngine.Localization.PropertyVariants.TrackedProperties, + asm: Unity.Localization} + data: + m_Localized: + m_TableReference: + m_TableCollectionName: GUID:c84355079ab3f3e4f8f3812258805f86 + m_TableEntryReference: + m_KeyId: 7933561489039360 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_PropertyPath: m_text +--- !u!1 &8203317146764388448 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 5384230387207399056} + - component: {fileID: 1440642196620937798} + - component: {fileID: 7293745301264864356} + m_Layer: 16 + m_Name: Background + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &5384230387207399056 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8203317146764388448} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0.0021666286, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 6721629502030059466} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!33 &1440642196620937798 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8203317146764388448} + m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &7293745301264864356 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8203317146764388448} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 39d7053101c6e8e4b8d692eddc65d2b2, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 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 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!1 &8230375728890308425 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1506107517258712976} + - component: {fileID: 1482784536010354649} + - component: {fileID: 5311018060250719400} + m_Layer: 16 + m_Name: Google_Logo + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1506107517258712976 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8230375728890308425} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: -0.9828, y: 0.26200008, z: -0.01} + m_LocalScale: {x: 0.2649999, y: 0.2649999, z: 0.2649999} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1432546188030660464} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!33 &1482784536010354649 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8230375728890308425} + m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &5311018060250719400 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8230375728890308425} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 63abc547c73548943a62755aac9edc7b, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 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 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!1 &8300865502376788124 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 3215585481372348197} + - component: {fileID: 4397428889506138906} + - component: {fileID: 7525156312729440484} + - component: {fileID: 7528125410182563106} + m_Layer: 16 + m_Name: Got it + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &3215585481372348197 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8300865502376788124} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: -0.029333334} + m_LocalScale: {x: 2.9528668, y: 5.9057336, z: 2.9528668} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 6721629502030059466} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0.141, y: 0} + m_SizeDelta: {x: 0.25, y: 0.15} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!23 &4397428889506138906 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8300865502376788124} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 0 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 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 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!114 &7525156312729440484 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8300865502376788124} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 9541d86e2fd84c1d9990edf0852d74ab, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_text: GOT IT + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} + m_sharedMaterial: {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4294967295 + m_fontColor: {r: 1, g: 1, b: 1, a: 1} + m_enableVertexGradient: 0 + m_colorMode: 3 + m_fontColorGradient: + topLeft: {r: 1, g: 1, b: 1, a: 1} + topRight: {r: 1, g: 1, b: 1, a: 1} + bottomLeft: {r: 1, g: 1, b: 1, a: 1} + bottomRight: {r: 1, g: 1, b: 1, a: 1} + m_fontColorGradientPreset: {fileID: 0} + m_spriteAsset: {fileID: 0} + m_tintAllSprites: 0 + m_StyleSheet: {fileID: 0} + m_TextStyleHashCode: -1183493901 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_fontSize: 0.64 + m_fontSizeBase: 0.64 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_HorizontalAlignment: 2 + m_VerticalAlignment: 512 + m_textAlignment: 65535 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_enableWordWrapping: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 0 + m_isCullingEnabled: 0 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_IsTextObjectScaleStatic: 0 + m_VertexBufferAutoSizeReduction: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + _SortingLayer: 0 + _SortingLayerID: 0 + _SortingOrder: 0 + m_hasFontAssetChanged: 0 + m_renderer: {fileID: 4397428889506138906} + m_maskType: 0 +--- !u!114 &7528125410182563106 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8300865502376788124} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 69beb381e244f92449b8c4cf954630e9, type: 3} + m_Name: + m_EditorClassIdentifier: + m_TrackedObjects: + - rid: 3215294302546034844 + references: + version: 2 + RefIds: + - rid: 3215294302546034844 + type: {class: TrackedUGuiGraphic, ns: UnityEngine.Localization.PropertyVariants.TrackedObjects, + asm: Unity.Localization} + data: + m_Target: {fileID: 7525156312729440484} + m_TrackedProperties: + items: + - rid: 3215294302546034845 + m_UpdateType: 0 + - rid: 3215294302546034845 + type: {class: LocalizedStringProperty, ns: UnityEngine.Localization.PropertyVariants.TrackedProperties, + asm: Unity.Localization} + data: + m_Localized: + m_TableReference: + m_TableCollectionName: GUID:c84355079ab3f3e4f8f3812258805f86 + m_TableEntryReference: + m_KeyId: 76036746777255936 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_PropertyPath: m_text +--- !u!1 &8372598602804526943 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1432546188030660464} + m_Layer: 16 + m_Name: Google_SignedOutElements + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1432546188030660464 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8372598602804526943} + serializedVersion: 2 + 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_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 8671432921432109627} + - {fileID: 1506107517258712976} + - {fileID: 277837882360728660} + - {fileID: 6952797202003472198} + - {fileID: 7893921961113671483} + m_Father: {fileID: 5854179938074699431} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &8374217926999613278 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1766577842652504206} + m_Layer: 16 + m_Name: UnavilableElements + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 0 +--- !u!4 &1766577842652504206 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8374217926999613278} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: -0.477, y: 0.135, z: 0} + m_LocalScale: {x: 0.85, y: 0.8500001, z: 0.8500001} + m_ConstrainProportionsScale: 1 + m_Children: + - {fileID: 9062749716723118463} + - {fileID: 1698918594952708344} + m_Father: {fileID: 8645625734765961102} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &8485803142575213209 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1698918594952708344} + - component: {fileID: 1322583919428993473} + - component: {fileID: 3928356307148317847} + - component: {fileID: 4196125711076099861} + m_Layer: 0 + m_Name: Description + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1698918594952708344 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8485803142575213209} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: -0.0025} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1766577842652504206} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0.058} + m_SizeDelta: {x: 2.5, y: 0.7} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!23 &1322583919428993473 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8485803142575213209} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 0 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 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 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!114 &3928356307148317847 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8485803142575213209} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 9541d86e2fd84c1d9990edf0852d74ab, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_text: Accounts are temporarily\nunavailable on this platform. + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} + m_sharedMaterial: {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4286085240 + m_fontColor: {r: 0.47058824, g: 0.47058824, b: 0.47058824, a: 1} + m_enableVertexGradient: 0 + m_colorMode: 3 + m_fontColorGradient: + topLeft: {r: 1, g: 1, b: 1, a: 1} + topRight: {r: 1, g: 1, b: 1, a: 1} + bottomLeft: {r: 1, g: 1, b: 1, a: 1} + bottomRight: {r: 1, g: 1, b: 1, a: 1} + m_fontColorGradientPreset: {fileID: 0} + m_spriteAsset: {fileID: 0} + m_tintAllSprites: 0 + m_StyleSheet: {fileID: 0} + m_TextStyleHashCode: -1183493901 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_fontSize: 1.275 + m_fontSizeBase: 1.275 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_HorizontalAlignment: 2 + m_VerticalAlignment: 512 + m_textAlignment: 65535 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_enableWordWrapping: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 0 + m_isCullingEnabled: 0 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_IsTextObjectScaleStatic: 0 + m_VertexBufferAutoSizeReduction: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + _SortingLayer: 0 + _SortingLayerID: 0 + _SortingOrder: 0 + m_hasFontAssetChanged: 0 + m_renderer: {fileID: 1322583919428993473} + m_maskType: 0 +--- !u!114 &4196125711076099861 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8485803142575213209} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 69beb381e244f92449b8c4cf954630e9, type: 3} + m_Name: + m_EditorClassIdentifier: + m_TrackedObjects: + - rid: 3215294302546034856 + references: + version: 2 + RefIds: + - rid: 3215294302546034856 + type: {class: TrackedUGuiGraphic, ns: UnityEngine.Localization.PropertyVariants.TrackedObjects, + asm: Unity.Localization} + data: + m_Target: {fileID: 3928356307148317847} + m_TrackedProperties: + items: + - rid: 3215294302546034857 + m_UpdateType: 0 + - rid: 3215294302546034857 + type: {class: LocalizedStringProperty, ns: UnityEngine.Localization.PropertyVariants.TrackedProperties, + asm: Unity.Localization} + data: + m_Localized: + m_TableReference: + m_TableCollectionName: GUID:c84355079ab3f3e4f8f3812258805f86 + m_TableEntryReference: + m_KeyId: 147094689821290496 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_PropertyPath: m_text +--- !u!1 &8579567244815457455 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1741904442304953456} + - component: {fileID: 1069378607617687420} + - component: {fileID: 9098812290505878358} + - component: {fileID: 215621484757398494} + - component: {fileID: 2602589182038582116} + m_Layer: 16 + m_Name: Drive_Link + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1741904442304953456 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8579567244815457455} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: -0.62, y: -0.576, z: -0.02500001} + m_LocalScale: {x: 0.7, y: 0.18, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 798000693479046927} + - {fileID: 1180802039870758397} + - {fileID: 4153333614772809210} + - {fileID: 7758143906596955047} + m_Father: {fileID: 1411852402157678472} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!33 &1069378607617687420 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8579567244815457455} + m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &9098812290505878358 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8579567244815457455} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: c731e5e6519d8354094a034ff2457c95, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 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 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!114 &215621484757398494 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8579567244815457455} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fc12adcafa62a22458e635d2ee7e78b5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_DescriptionType: -1 + m_DescriptionYOffset: 0 + m_DescriptionText: + m_LocalizedDescription: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_DescriptionTextExtra: + m_LocalizedDescriptionExtra: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_DescriptionActivateSpeed: 12 + m_DescriptionZScale: 1 + m_ButtonTexture: {fileID: 0} + m_AtlasTexture: 0 + m_ToggleButton: 0 + m_LongPressReleaseButton: 0 + m_ButtonHasPressedAudio: 1 + m_ZAdjustHover: -0.02 + m_ZAdjustClick: 0.05 + m_HoverScale: 1.1 + m_HoverBoxColliderGrow: 0.2 + m_AddOverlay: 0 + m_Command: 73 + m_CommandParam: 0 + m_CommandParam2: -1 + m_RequiresPopup: 0 + m_CenterPopupOnButton: 0 + m_PopupOffset: {x: 0, y: 0, z: 0} + m_PopupText: + m_LocalizedPopup: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_ToggleOnDescription: + m_LocalizedToggleOnDescription: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_ToggleOnTexture: {fileID: 0} + m_AllowUnavailable: 0 + m_LinkedUIObject: {fileID: 0} + m_CommandIgnored: 0 + references: + version: 2 + RefIds: [] +--- !u!65 &2602589182038582116 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8579567244815457455} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Size: {x: 1, y: 1, z: 0.1} + m_Center: {x: 0, y: 0, z: -0.01} +--- !u!1 &8644312780941313480 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 8425076696762416562} + - component: {fileID: 8620201613594084264} + - component: {fileID: 8530386015597152794} + m_Layer: 0 + m_Name: Google_Name + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &8425076696762416562 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8644312780941313480} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: -0.010000003} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1411852402157678472} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: -1.169, y: -0.477} + m_SizeDelta: {x: 1.1, y: 0.35} + m_Pivot: {x: 0, y: 0} +--- !u!23 &8620201613594084264 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8644312780941313480} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 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 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!114 &8530386015597152794 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8644312780941313480} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 9541d86e2fd84c1d9990edf0852d74ab, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_text: Longnamefirstname Longnamesurname + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} + m_sharedMaterial: {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4294967295 + m_fontColor: {r: 1, g: 1, b: 1, a: 1} + m_enableVertexGradient: 0 + m_colorMode: 3 + m_fontColorGradient: + topLeft: {r: 1, g: 1, b: 1, a: 1} + topRight: {r: 1, g: 1, b: 1, a: 1} + bottomLeft: {r: 1, g: 1, b: 1, a: 1} + bottomRight: {r: 1, g: 1, b: 1, a: 1} + m_fontColorGradientPreset: {fileID: 0} + m_spriteAsset: {fileID: 0} + m_tintAllSprites: 0 + m_StyleSheet: {fileID: 0} + m_TextStyleHashCode: -1183493901 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_fontSize: 1.3 + m_fontSizeBase: 1.3 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_HorizontalAlignment: 2 + m_VerticalAlignment: 256 + m_textAlignment: 65535 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: -22 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_enableWordWrapping: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 3 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 0 + m_isCullingEnabled: 0 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_IsTextObjectScaleStatic: 0 + m_VertexBufferAutoSizeReduction: 1 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + _SortingLayer: 0 + _SortingLayerID: 0 + _SortingOrder: 0 + m_hasFontAssetChanged: 0 + m_renderer: {fileID: 8620201613594084264} + m_maskType: 0 +--- !u!1 &8644332586413500038 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 8645625732761162234} + - component: {fileID: 8610995069649507040} + - component: {fileID: 8621276525763300312} + m_Layer: 16 + m_Name: Google_ProfilePhoto + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &8645625732761162234 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8644332586413500038} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: -0.621, y: 0.11, z: -0.010000025} + m_LocalScale: {x: 0.4, y: 0.4, z: 0.4} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 8645625732756982244} + - {fileID: 3135609562369966535} + m_Father: {fileID: 1411852402157678472} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!33 &8610995069649507040 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8644332586413500038} + m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &8621276525763300312 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8644332586413500038} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 0 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: da7f0d43a22e3f24bbc517466728866f, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 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 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!1 &8644332586423700726 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 8645625732756982244} + - component: {fileID: 8610995080555659526} + - component: {fileID: 8621276525021700672} + m_Layer: 16 + m_Name: PhotoBGW + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &8645625732756982244 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8644332586423700726} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0.0022857143} + m_LocalScale: {x: 1.1, y: 1.1, z: 1.1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 8645625732761162234} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!33 &8610995080555659526 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8644332586423700726} + m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &8621276525021700672 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8644332586423700726} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 0 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 0c298b4a41e7c5b4daf56d8987a83788, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 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 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!1 &8644332587409793350 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 8645625740661137770} + - component: {fileID: 8610995081492312010} + - component: {fileID: 8621276525838995664} + m_Layer: 16 + m_Name: PopupBorder + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &8645625740661137770 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8644332587409793350} + serializedVersion: 2 + m_LocalRotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071067} + m_LocalPosition: {x: -0, y: 0, z: 0} + m_LocalScale: {x: 100, y: 100, z: 100} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 8645625735778197046} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!33 &8610995081492312010 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8644332587409793350} + m_Mesh: {fileID: 4300000, guid: 9732ef7c98f40b34f8094be4fc6cd363, type: 3} +--- !u!23 &8621276525838995664 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8644332587409793350} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 77dd4ff8b1158a84397aba783cd0af05, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 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 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!1 &8644332587479430734 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 8645625734765961102} + - component: {fileID: 8529915923179660036} + - component: {fileID: 8580401944159525890} + - component: {fileID: 8533537593755566908} + m_Layer: 16 + m_Name: PopUpWindow_Accounts + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &8645625734765961102 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8644332587479430734} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 3, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 8645625735416266758} + - {fileID: 8645625734681381188} + - {fileID: 4825048073929942150} + - {fileID: 3576301794080265196} + - {fileID: 3457603883277620212} + - {fileID: 6373137851377895237} + - {fileID: 1766577842652504206} + - {fileID: 8645625735778197046} + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &8529915923179660036 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8644332587479430734} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 3fc89a0b3103cba4a9a28c525afa2ce4, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Background: {fileID: 8644332588524666284} + m_TopBorder: {fileID: 8644332587409793350} + m_BottomBorder: {fileID: 8644332587409793350} + m_WindowText: {fileID: 2543170560323612900} + m_CharacterWidth: 0.075 + m_SubtitleCharacterWidth: 0.05625 + m_ButtonWidth: 0.5 + m_BaseButtonOffset: {x: 0, y: 0, z: 0} + m_ReticleBounds: {x: 3.4, y: 3, z: -0.35} + m_PopUpForwardOffset: -0.25 + m_AutoPlaceButtons: [] + m_TransitionDuration: 0.1 + m_OpenDelay: 0 + m_Persistent: 0 + m_AudioOnOpen: 1 + m_BlockUndoRedo: 0 + m_IsLongPressPopUp: 0 + m_OrderedPageButtons: [] + m_PrevButton: {fileID: 0} + m_NextButton: {fileID: 0} + m_ColorTransitionDuration: 0 + m_GoogleSignedInElements: {fileID: 7292193688806996409} + m_GoogleSignedOutElements: {fileID: 8372598602804526943} + m_GoogleConfirmSignOutElements: {fileID: 9078849995330061814} + m_SketchfabSignedInElements: {fileID: 5866976969575595662} + m_SketchfabSignedOutElements: {fileID: 7620355729290749329} + m_SketchfabConfirmSignOutElements: {fileID: 5649685825589421528} + m_IcosaSignedInElements: {fileID: 162347472523419310} + m_IcosaSignedOutElements: {fileID: 3893413551512185020} + m_IcosaConfirmSignOutElements: {fileID: 2027372909421917180} + m_IcosaLoginElements: {fileID: 281059592884163862} + m_GooglePhoto: {fileID: 8621276525763300312} + m_SketchfabPhoto: {fileID: 6282619306390002852} + m_IcosaPhoto: {fileID: 5558472698597662980} + m_GoogleNameText: {fileID: 8530386015597152794} + m_SketchfabNameText: {fileID: 3509174102411407934} + m_IcosaNameText: {fileID: 6196538126404319155} + m_GenericPhoto: {fileID: 2800000, guid: edd2e08d6f610b840828462609546014, type: 3} + m_Accounts: {fileID: 8644332589018115638} + m_TakeOffHeadset: {fileID: 8644332588631379036} + m_GoogleInfoElements: {fileID: 8025577052483214110} + m_DriveInfoElements: {fileID: 5048206632594256402} + m_SketchfabInfoElements: {fileID: 2181120061148835783} + m_IcosaInfoElements: {fileID: 8854873750265266201} + m_UnavailableElements: {fileID: 8374217926999613278} + m_DriveSyncEnabledElements: {fileID: 3439436514154816488} + m_DriveSyncDisabledElements: {fileID: 8663098325165672148} + m_DriveFullElements: {fileID: 5684969559238275584} + m_DriveSyncIconEnabled: {fileID: 5921053250823053932} + m_DriveSyncIconDisabled: {fileID: 4316944982740412120} + m_DriveSyncIconDriveFull: {fileID: 2727968127303647375} + m_BackupCompleteElements: {fileID: 3102330576168079932} + m_BackingUpElements: {fileID: 1118210038496079559} + m_BackingUpProgress: {fileID: 554234529220568430} + m_ConfirmLoginElements: {fileID: 0} + m_SaveAndProceedButton: {fileID: 0} +--- !u!65 &8580401944159525890 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8644332587479430734} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Size: {x: 3.4, y: 2.8, z: 0.01} + m_Center: {x: 0.2, y: -0.6, z: -0.01} +--- !u!114 &8533537593755566908 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8644332587479430734} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 739d5b1996234d64992a2ae60c3723e9, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!1 &8644332587709734578 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 8645625735778197046} + m_Layer: 16 + m_Name: ProfilePopupMesh + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &8645625735778197046 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8644332587709734578} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: -0.349, z: 0} + m_LocalScale: {x: 1.21, y: 1.21, z: 1.21} + m_ConstrainProportionsScale: 1 + m_Children: + - {fileID: 8645625733637814676} + - {fileID: 8645625740661137770} + m_Father: {fileID: 8645625734765961102} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &8644332588524666284 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 8645625733637814676} + - component: {fileID: 8610995081988753086} + - component: {fileID: 8621276526632499898} + m_Layer: 16 + m_Name: PopupBg + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &8645625733637814676 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8644332588524666284} + serializedVersion: 2 + m_LocalRotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071067} + m_LocalPosition: {x: -0, y: 0, z: 0} + m_LocalScale: {x: 100, y: 100, z: 100} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 8645625735778197046} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!33 &8610995081988753086 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8644332588524666284} + m_Mesh: {fileID: 4300002, guid: 9732ef7c98f40b34f8094be4fc6cd363, type: 3} +--- !u!23 &8621276526632499898 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8644332588524666284} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: db0305ff9081c3b448ac79e85d26e5d4, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 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 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!1 &8644332588631379036 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 8645625734681381188} + m_Layer: 16 + m_Name: RemoveHeadsetElements + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 0 +--- !u!4 &8645625734681381188 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8644332588631379036} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0.13499999, z: 0} + m_LocalScale: {x: 0.85, y: 0.8500001, z: 0.8500001} + m_ConstrainProportionsScale: 1 + m_Children: + - {fileID: 1799102450530444095} + - {fileID: 8645625734146380956} + - {fileID: 8645625735159627316} + m_Father: {fileID: 8645625734765961102} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &8644332588836208674 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1799102450530444095} + - component: {fileID: 8621276525058679400} + - component: {fileID: 5265230356848354045} + - component: {fileID: 6723664597259726558} + m_Layer: 0 + m_Name: TakeOffHeadset + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1799102450530444095 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8644332588836208674} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: -0.0025} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 8645625734681381188} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0.55} + m_SizeDelta: {x: 20, y: 5} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!23 &8621276525058679400 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8644332588836208674} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 0 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 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 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!114 &5265230356848354045 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8644332588836208674} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 9541d86e2fd84c1d9990edf0852d74ab, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_text: Take Off Headset + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} + m_sharedMaterial: {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4294967295 + m_fontColor: {r: 1, g: 1, b: 1, a: 1} + m_enableVertexGradient: 0 + m_colorMode: 3 + m_fontColorGradient: + topLeft: {r: 1, g: 1, b: 1, a: 1} + topRight: {r: 1, g: 1, b: 1, a: 1} + bottomLeft: {r: 1, g: 1, b: 1, a: 1} + bottomRight: {r: 1, g: 1, b: 1, a: 1} + m_fontColorGradientPreset: {fileID: 0} + m_spriteAsset: {fileID: 0} + m_tintAllSprites: 0 + m_StyleSheet: {fileID: 0} + m_TextStyleHashCode: -1183493901 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_fontSize: 1.91 + m_fontSizeBase: 1.91 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_HorizontalAlignment: 2 + m_VerticalAlignment: 512 + m_textAlignment: 65535 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_enableWordWrapping: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 0 + m_isCullingEnabled: 0 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_IsTextObjectScaleStatic: 0 + m_VertexBufferAutoSizeReduction: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + _SortingLayer: 0 + _SortingLayerID: 0 + _SortingOrder: 0 + m_hasFontAssetChanged: 0 + m_renderer: {fileID: 8621276525058679400} + m_maskType: 0 +--- !u!114 &6723664597259726558 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8644332588836208674} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 69beb381e244f92449b8c4cf954630e9, type: 3} + m_Name: + m_EditorClassIdentifier: + m_TrackedObjects: + - rid: 3215294302546034842 + references: + version: 2 + RefIds: + - rid: 3215294302546034842 + type: {class: TrackedUGuiGraphic, ns: UnityEngine.Localization.PropertyVariants.TrackedObjects, + asm: Unity.Localization} + data: + m_Target: {fileID: 5265230356848354045} + m_TrackedProperties: + items: + - rid: 3215294302546034843 + m_UpdateType: 0 + - rid: 3215294302546034843 + type: {class: LocalizedStringProperty, ns: UnityEngine.Localization.PropertyVariants.TrackedProperties, + asm: Unity.Localization} + data: + m_Localized: + m_TableReference: + m_TableCollectionName: GUID:c84355079ab3f3e4f8f3812258805f86 + m_TableEntryReference: + m_KeyId: 76134950436921344 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_PropertyPath: m_text +--- !u!1 &8644332589018115638 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 8645625735416266758} + m_Layer: 16 + m_Name: ViewingAccountsElements + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &8645625735416266758 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8644332589018115638} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0.13499999, z: 0} + m_LocalScale: {x: 0.85, y: 0.8500001, z: 0.8500001} + m_ConstrainProportionsScale: 1 + m_Children: + - {fileID: 6204130650882258485} + - {fileID: 1182483975005714860} + - {fileID: 5854179938074699431} + - {fileID: 149137880941958609} + - {fileID: 7706333168622570552} + m_Father: {fileID: 8645625734765961102} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &8644332589239274156 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 8645625735159627316} + - component: {fileID: 8610995070916950296} + - component: {fileID: 8621276523770920886} + - component: {fileID: 8580401943792562782} + - component: {fileID: 853645773711861975} + m_Layer: 14 + m_Name: ConfirmationButton + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &8645625735159627316 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8644332589239274156} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: -0.434, z: -0.08} + m_LocalScale: {x: 0.6, y: 0.29999998, z: 0.29999998} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 1829480651769887961} + - {fileID: 8645625732950447588} + m_Father: {fileID: 8645625734681381188} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!33 &8610995070916950296 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8644332589239274156} + m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &8621276523770920886 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8644332589239274156} + m_Enabled: 0 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 0 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 3c8ca511828182747a0b79564892ec57, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 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 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!65 &8580401943792562782 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8644332589239274156} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Size: {x: 1, y: 1, z: 0.01} + m_Center: {x: 0, y: 0, z: -0.01} +--- !u!114 &853645773711861975 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8644332589239274156} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fc12adcafa62a22458e635d2ee7e78b5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_DescriptionType: -1 + m_DescriptionYOffset: 0 + m_DescriptionText: + m_LocalizedDescription: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_DescriptionTextExtra: + m_LocalizedDescriptionExtra: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_DescriptionActivateSpeed: 12 + m_DescriptionZScale: 1 + m_ButtonTexture: {fileID: 0} + m_AtlasTexture: 0 + m_ToggleButton: 0 + m_LongPressReleaseButton: 0 + m_ButtonHasPressedAudio: 1 + m_ZAdjustHover: -0.02 + m_ZAdjustClick: 0.05 + m_HoverScale: 1.1 + m_HoverBoxColliderGrow: 0.2 + m_AddOverlay: 0 + m_Command: 0 + m_CommandParam: -1 + m_CommandParam2: -1 + m_RequiresPopup: 0 + m_CenterPopupOnButton: 0 + m_PopupOffset: {x: 0, y: 0, z: 0} + m_PopupText: + m_LocalizedPopup: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_ToggleOnDescription: + m_LocalizedToggleOnDescription: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_ToggleOnTexture: {fileID: 0} + m_AllowUnavailable: 0 + m_LinkedUIObject: {fileID: 0} + m_CommandIgnored: 0 + references: + version: 2 + RefIds: [] +--- !u!1 &8644332589642346024 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 8645625734146380956} + - component: {fileID: 8610995080664749698} + - component: {fileID: 8621276525178098980} + m_Layer: 16 + m_Name: Animation + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &8645625734146380956 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8644332589642346024} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0.099, z: -0.0025} + m_LocalScale: {x: 0.7, y: 0.7, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 8645625734681381188} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!33 &8610995080664749698 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8644332589642346024} + m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &8621276525178098980 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8644332589642346024} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 0 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: cc3ea5371dc184af2a1640b84d45f29e, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 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 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!1 &8644332589849401822 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 8645625732950447588} + - component: {fileID: 8610995080173436830} + - component: {fileID: 8621276523781374462} + m_Layer: 16 + m_Name: Background + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &8645625732950447588 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8644332589849401822} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0.0021666286, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 8645625735159627316} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!33 &8610995080173436830 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8644332589849401822} + m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &8621276523781374462 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8644332589849401822} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 39d7053101c6e8e4b8d692eddc65d2b2, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 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 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!1 &8644332589952109232 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 6204130650882258485} + - component: {fileID: 7331502488059647707} + - component: {fileID: 2543170560323612900} + - component: {fileID: 3707599773211769618} + m_Layer: 16 + m_Name: Title + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &6204130650882258485 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8644332589952109232} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: -0.0025} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 8645625735416266758} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: -1.171, y: 0.731} + m_SizeDelta: {x: 2.37, y: 0.3} + m_Pivot: {x: 0, y: 1} +--- !u!23 &7331502488059647707 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8644332589952109232} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + 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 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!114 &2543170560323612900 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8644332589952109232} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 9541d86e2fd84c1d9990edf0852d74ab, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_text: Accounts + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} + m_sharedMaterial: {fileID: 2133298, guid: fce54057bad3d2d4cb3c36ee394be518, type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4294967295 + m_fontColor: {r: 1, g: 1, b: 1, a: 1} + m_enableVertexGradient: 0 + m_colorMode: 3 + m_fontColorGradient: + topLeft: {r: 1, g: 1, b: 1, a: 1} + topRight: {r: 1, g: 1, b: 1, a: 1} + bottomLeft: {r: 1, g: 1, b: 1, a: 1} + bottomRight: {r: 1, g: 1, b: 1, a: 1} + m_fontColorGradientPreset: {fileID: 0} + m_spriteAsset: {fileID: 0} + m_tintAllSprites: 0 + m_StyleSheet: {fileID: 0} + m_TextStyleHashCode: -1183493901 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_fontSize: 1.92 + m_fontSizeBase: 1.92 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 0 + m_HorizontalAlignment: 1 + m_VerticalAlignment: 256 + m_textAlignment: 65535 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_enableWordWrapping: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 0 + m_isCullingEnabled: 0 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_IsTextObjectScaleStatic: 0 + m_VertexBufferAutoSizeReduction: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + _SortingLayer: 0 + _SortingLayerID: 0 + _SortingOrder: 0 + m_hasFontAssetChanged: 0 + m_renderer: {fileID: 7331502488059647707} + m_maskType: 0 +--- !u!114 &3707599773211769618 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8644332589952109232} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 69beb381e244f92449b8c4cf954630e9, type: 3} + m_Name: + m_EditorClassIdentifier: + m_TrackedObjects: + - rid: 3215294302546034834 + references: + version: 2 + RefIds: + - rid: 3215294302546034834 + type: {class: TrackedUGuiGraphic, ns: UnityEngine.Localization.PropertyVariants.TrackedObjects, + asm: Unity.Localization} + data: + m_Target: {fileID: 2543170560323612900} + m_TrackedProperties: + items: + - rid: 3215294302546034835 + m_UpdateType: 0 + - rid: 3215294302546034835 + type: {class: LocalizedStringProperty, ns: UnityEngine.Localization.PropertyVariants.TrackedProperties, + asm: Unity.Localization} + data: + m_Localized: + m_TableReference: + m_TableCollectionName: GUID:c84355079ab3f3e4f8f3812258805f86 + m_TableEntryReference: + m_KeyId: 76131299773440000 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_PropertyPath: m_text +--- !u!1 &8644332590165761558 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 8645625734912766616} + - component: {fileID: 8610995070142662328} + - component: {fileID: 8621276526839603414} + - component: {fileID: 6538246798073148024} + - component: {fileID: 8580401943618346556} + m_Layer: 16 + m_Name: Google_SignOut + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &8645625734912766616 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8644332590165761558} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: -0.193, y: 0.247, z: -0.02499998} + m_LocalScale: {x: 0.25, y: 0.24999991, z: 0.2499999} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 1411852402157678472} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!33 &8610995070142662328 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8644332590165761558} + m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &8621276526839603414 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8644332590165761558} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 0 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 3c8ca511828182747a0b79564892ec57, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 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 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!114 &6538246798073148024 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8644332590165761558} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fc12adcafa62a22458e635d2ee7e78b5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_DescriptionType: 0 + m_DescriptionYOffset: 0 + m_DescriptionText: POPUP_ACCOUNTS_SIGNOUT_BUTTON_DESCRIPTION + m_LocalizedDescription: + m_TableReference: + m_TableCollectionName: GUID:c84355079ab3f3e4f8f3812258805f86 + m_TableEntryReference: + m_KeyId: 15522362785837056 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_DescriptionTextExtra: + m_LocalizedDescriptionExtra: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_DescriptionActivateSpeed: 12 + m_DescriptionZScale: 1 + m_ButtonTexture: {fileID: 2800000, guid: 42f600d7b08f5514ebdcf4604e0cfa6c, type: 3} + m_AtlasTexture: 1 + m_ToggleButton: 0 + m_LongPressReleaseButton: 0 + m_ButtonHasPressedAudio: 1 + m_ZAdjustHover: -0.02 + m_ZAdjustClick: 0.05 + m_HoverScale: 1.1 + m_HoverBoxColliderGrow: 0.2 + m_AddOverlay: 0 + m_Command: 98 + m_CommandParam: 1 + m_CommandParam2: -1 + m_RequiresPopup: 0 + m_CenterPopupOnButton: 0 + m_PopupOffset: {x: 0, y: 0, z: 0} + m_PopupText: + m_LocalizedPopup: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_ToggleOnDescription: + m_LocalizedToggleOnDescription: + m_TableReference: + m_TableCollectionName: + m_TableEntryReference: + m_KeyId: 0 + m_Key: + m_FallbackState: 0 + m_WaitForCompletion: 0 + m_LocalVariables: [] + m_ToggleOnTexture: {fileID: 0} + m_AllowUnavailable: 0 + m_LinkedUIObject: {fileID: 0} + m_CommandIgnored: 1 + references: + version: 2 + RefIds: [] +--- !u!65 &8580401943618346556 +BoxCollider: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8644332590165761558} + m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 + m_IsTrigger: 0 + m_ProvidesContacts: 0 + m_Enabled: 1 + serializedVersion: 3 + m_Size: {x: 1, y: 1.0000001, z: 0.1} + m_Center: {x: 0, y: 0, z: -0.01} +--- !u!1 &8854873750265266201 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 6373137851377895237} + m_Layer: 16 + m_Name: IcosaInfoElements + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 0 +--- !u!4 &6373137851377895237 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8854873750265266201} + serializedVersion: 2 + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0.135, z: 0} + m_LocalScale: {x: 0.85, y: 0.8500001, z: 0.8500001} + m_ConstrainProportionsScale: 1 + m_Children: + - {fileID: 8304354692682796117} + - {fileID: 7219417712597752172} + - {fileID: 7500850895307564819} + m_Father: {fileID: 8645625734765961102} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &9067465071141378777 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 149137880941958609} + m_Layer: 16 + m_Name: Sketchfab + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &149137880941958609 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 9067465071141378777} + serializedVersion: 2 + 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_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 529827201699571093} + - {fileID: 534589999851858800} + - {fileID: 6423827612944397798} + m_Father: {fileID: 8645625735416266758} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &9078849995330061814 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 7741920746089690377} + m_Layer: 16 + m_Name: Google_ConfirmSignOutElements + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &7741920746089690377 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 9078849995330061814} + serializedVersion: 2 + 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_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 2399947737502410141} + - {fileID: 6112888683899395240} + - {fileID: 5446221535905318599} + - {fileID: 4590447671262214820} + m_Father: {fileID: 5854179938074699431} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &9188801593698870886 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 906844544403122228} + - component: {fileID: 2379879017139536075} + - component: {fileID: 4874927894839058143} + m_Layer: 16 + m_Name: Background + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &906844544403122228 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 9188801593698870886} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0.045} + m_LocalScale: {x: 2, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 5520953697447238279} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!33 &2379879017139536075 +MeshFilter: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 9188801593698870886} + m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} +--- !u!23 &4874927894839058143 +MeshRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 9188801593698870886} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 2100000, guid: 0ead8b8e224bcf040862605f5eed7211, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 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 + m_AdditionalVertexStreams: {fileID: 0} +--- !u!1001 &3407973161605095053 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + serializedVersion: 3 + m_TransformParent: {fileID: 282387885870267606} + m_Modifications: + - target: {fileID: 1934243545717122, guid: ef7eb6dda2db50c4bbf6c682e4a21736, type: 3} + propertyPath: m_Name + value: Keyboard + objectReference: {fileID: 0} + - target: {fileID: 114387715371604348, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: _maxLineLength + value: 5 + objectReference: {fileID: 0} + - target: {fileID: 114387715371604348, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: _capsLockEnabled + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 114387715371604348, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: _lineDisplayUsesCursor + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 114387715371604348, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: _consoleDisplayUsesCursor + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 114773793380896770, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_Enabled + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 199519161696781973, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_SizeDelta.x + value: 2222 + objectReference: {fileID: 0} + - target: {fileID: 199519161696781973, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_SizeDelta.y + value: 444 + objectReference: {fileID: 0} + - target: {fileID: 224533170015225100, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalScale.x + value: 1.1855999 + objectReference: {fileID: 0} + - target: {fileID: 224533170015225100, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalScale.y + value: 1.1855999 + objectReference: {fileID: 0} + - target: {fileID: 224533170015225100, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalScale.z + value: 1.1855999 + objectReference: {fileID: 0} + - target: {fileID: 224533170015225100, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalPosition.z + value: 0.012025 + objectReference: {fileID: 0} + - target: {fileID: 224533170015225100, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_AnchoredPosition.x + value: 256.68396 + objectReference: {fileID: 0} + - target: {fileID: 224533170015225100, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_AnchoredPosition.y + value: -246.59 + objectReference: {fileID: 0} + - target: {fileID: 224560323429904302, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_Pivot.x + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 224560323429904302, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_Pivot.y + value: 0.5 + objectReference: {fileID: 0} + - target: {fileID: 224560323429904302, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_RootOrder + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 224560323429904302, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_AnchorMax.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 224560323429904302, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_AnchorMax.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 224560323429904302, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_AnchorMin.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 224560323429904302, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_AnchorMin.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 224560323429904302, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_SizeDelta.x + value: 2700 + objectReference: {fileID: 0} + - target: {fileID: 224560323429904302, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_SizeDelta.y + value: 1080 + objectReference: {fileID: 0} + - target: {fileID: 224560323429904302, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalScale.x + value: 0.00089999987 + objectReference: {fileID: 0} + - target: {fileID: 224560323429904302, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalScale.y + value: 0.00090000004 + objectReference: {fileID: 0} + - target: {fileID: 224560323429904302, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalScale.z + value: 0.00090000004 + objectReference: {fileID: 0} + - target: {fileID: 224560323429904302, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 224560323429904302, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 224560323429904302, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalPosition.z + value: -0.044 + objectReference: {fileID: 0} + - target: {fileID: 224560323429904302, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 224560323429904302, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalRotation.x + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 224560323429904302, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalRotation.y + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 224560323429904302, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalRotation.z + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 224560323429904302, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_AnchoredPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 224560323429904302, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_AnchoredPosition.y + value: -0.13 + objectReference: {fileID: 0} + - target: {fileID: 224560323429904302, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 224560323429904302, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 224560323429904302, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 224882291414706024, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalScale.x + value: 1.1855999 + objectReference: {fileID: 0} + - target: {fileID: 224882291414706024, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalScale.y + value: 1.1855999 + objectReference: {fileID: 0} + - target: {fileID: 224882291414706024, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalScale.z + value: 1.1855999 + objectReference: {fileID: 0} + - target: {fileID: 224882291414706024, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalPosition.z + value: 0.012025 + objectReference: {fileID: 0} + - target: {fileID: 224882291414706024, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_AnchoredPosition.x + value: 297 + objectReference: {fileID: 0} + - target: {fileID: 224882291414706024, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_AnchoredPosition.y + value: -673.41 + objectReference: {fileID: 0} + - target: {fileID: 224925074309398680, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalScale.x + value: 1.1855999 + objectReference: {fileID: 0} + - target: {fileID: 224925074309398680, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalScale.y + value: 1.1855999 + objectReference: {fileID: 0} + - target: {fileID: 224925074309398680, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalScale.z + value: 1.1855999 + objectReference: {fileID: 0} + - target: {fileID: 224925074309398680, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalPosition.z + value: 0.012025 + objectReference: {fileID: 0} + - target: {fileID: 224925074309398680, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_AnchoredPosition.x + value: 135.19006 + objectReference: {fileID: 0} + - target: {fileID: 224926869949627142, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalScale.x + value: 1.1856 + objectReference: {fileID: 0} + - target: {fileID: 224926869949627142, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalScale.y + value: 1.1856 + objectReference: {fileID: 0} + - target: {fileID: 224926869949627142, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalScale.z + value: 1.1856 + objectReference: {fileID: 0} + - target: {fileID: 224926869949627142, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalPosition.z + value: 0.012025 + objectReference: {fileID: 0} + - target: {fileID: 224926869949627142, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_AnchoredPosition.x + value: 78.839966 + objectReference: {fileID: 0} + - target: {fileID: 224926869949627142, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_AnchoredPosition.y + value: -33.17801 + objectReference: {fileID: 0} + - target: {fileID: 5277493517249866201, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_text + value: C + objectReference: {fileID: 0} + - target: {fileID: 5277493517303974699, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_text + value: R + objectReference: {fileID: 0} + - target: {fileID: 5277493517315999433, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_text + value: V + objectReference: {fileID: 0} + - target: {fileID: 5277493517320569316, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_text + value: Backspace + objectReference: {fileID: 0} + - target: {fileID: 5277493517320569316, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_fontSize + value: 80 + objectReference: {fileID: 0} + - target: {fileID: 5277493517320569316, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_fontColor32.rgba + value: 4294770430 + objectReference: {fileID: 0} + - target: {fileID: 5277493517334691012, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_text + value: Y + objectReference: {fileID: 0} + - target: {fileID: 5277493517390459847, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_text + value: Tab + objectReference: {fileID: 0} + - target: {fileID: 5277493517390459847, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_fontSize + value: 80 + objectReference: {fileID: 0} + - target: {fileID: 5277493517390459847, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_fontColor32.rgba + value: 4294770430 + objectReference: {fileID: 0} + - target: {fileID: 5277493517514550751, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_text + value: J + objectReference: {fileID: 0} + - target: {fileID: 5277493517658775782, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_text + value: S + objectReference: {fileID: 0} + - target: {fileID: 5277493517766971825, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_text + value: Caps Lock + objectReference: {fileID: 0} + - target: {fileID: 5277493517766971825, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_fontSize + value: 70.9 + objectReference: {fileID: 0} + - target: {fileID: 5277493517766971825, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_fontColor32.rgba + value: 4294770430 + objectReference: {fileID: 0} + - target: {fileID: 5277493517836040783, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_text + value: Control + objectReference: {fileID: 0} + - target: {fileID: 5277493517836040783, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_fontSize + value: 80 + objectReference: {fileID: 0} + - target: {fileID: 5277493517836040783, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_fontColor32.rgba + value: 4294770430 + objectReference: {fileID: 0} + - target: {fileID: 5277493517877139980, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_text + value: F + objectReference: {fileID: 0} + - target: {fileID: 5277493517906801478, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_text + value: Z + objectReference: {fileID: 0} + - target: {fileID: 5277493517921236477, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_text + value: N + objectReference: {fileID: 0} + - target: {fileID: 5277493517955558978, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_text + value: X + objectReference: {fileID: 0} + - target: {fileID: 5277493517967058681, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_text + value: G + objectReference: {fileID: 0} + - target: {fileID: 5277493518058433820, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_text + value: Q + objectReference: {fileID: 0} + - target: {fileID: 5277493518090577653, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_text + value: AltGr + objectReference: {fileID: 0} + - target: {fileID: 5277493518090577653, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_fontSize + value: 80 + objectReference: {fileID: 0} + - target: {fileID: 5277493518090577653, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_fontColor32.rgba + value: 4294770430 + objectReference: {fileID: 0} + - target: {fileID: 5277493518097974896, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_text + value: U + objectReference: {fileID: 0} + - target: {fileID: 5277493518109558583, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_text + value: A + objectReference: {fileID: 0} + - target: {fileID: 5277493518150738224, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_text + value: O + objectReference: {fileID: 0} + - target: {fileID: 5277493518218343584, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_text + value: D + objectReference: {fileID: 0} + - target: {fileID: 5277493518266940734, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_text + value: I + objectReference: {fileID: 0} + - target: {fileID: 5277493518340769154, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_text + value: Shift + objectReference: {fileID: 0} + - target: {fileID: 5277493518340769154, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_fontSize + value: 80 + objectReference: {fileID: 0} + - target: {fileID: 5277493518340769154, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_fontColor32.rgba + value: 4294770430 + objectReference: {fileID: 0} + - target: {fileID: 5277493518477428480, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_text + value: Control + objectReference: {fileID: 0} + - target: {fileID: 5277493518477428480, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_fontSize + value: 80 + objectReference: {fileID: 0} + - target: {fileID: 5277493518477428480, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_fontColor32.rgba + value: 4294770430 + objectReference: {fileID: 0} + - target: {fileID: 5277493518477510903, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_text + value: E + objectReference: {fileID: 0} + - target: {fileID: 5277493518499813032, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_text + value: H + objectReference: {fileID: 0} + - target: {fileID: 5277493518791869705, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_text + value: K + objectReference: {fileID: 0} + - target: {fileID: 5277493518803901753, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_text + value: L + objectReference: {fileID: 0} + - target: {fileID: 5277493518929165342, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_text + value: B + objectReference: {fileID: 0} + - target: {fileID: 5277493518960887007, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_text + value: Alt + objectReference: {fileID: 0} + - target: {fileID: 5277493518960887007, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_fontSize + value: 80 + objectReference: {fileID: 0} + - target: {fileID: 5277493518960887007, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_fontColor32.rgba + value: 4294770430 + objectReference: {fileID: 0} + - target: {fileID: 5277493519032514996, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_text + value: T + objectReference: {fileID: 0} + - target: {fileID: 5277493519050611944, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_text + value: W + objectReference: {fileID: 0} + - target: {fileID: 5277493519053288274, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_text + value: Enter + objectReference: {fileID: 0} + - target: {fileID: 5277493519053288274, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_fontSize + value: 80 + objectReference: {fileID: 0} + - target: {fileID: 5277493519053288274, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_fontColor32.rgba + value: 4294770430 + objectReference: {fileID: 0} + - target: {fileID: 5277493519190116170, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_text + value: Shift + objectReference: {fileID: 0} + - target: {fileID: 5277493519190116170, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_fontSize + value: 80 + objectReference: {fileID: 0} + - target: {fileID: 5277493519190116170, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_fontColor32.rgba + value: 4294770430 + objectReference: {fileID: 0} + - target: {fileID: 5277493519225887468, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_text + value: P + objectReference: {fileID: 0} + - target: {fileID: 5277493519272292233, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_text + value: M + objectReference: {fileID: 0} + - target: {fileID: 6442521557777233233, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalScale.x + value: 1.1855999 + objectReference: {fileID: 0} + - target: {fileID: 6442521557777233233, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalScale.y + value: 1.1855999 + objectReference: {fileID: 0} + - target: {fileID: 6442521557777233233, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalScale.z + value: 1.1855999 + objectReference: {fileID: 0} + - target: {fileID: 6442521557777233233, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalPosition.z + value: 0.012025 + objectReference: {fileID: 0} + - target: {fileID: 6442521557777233233, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_AnchoredPosition.x + value: 19.559937 + objectReference: {fileID: 0} + - target: {fileID: 6442521557777233233, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_AnchoredPosition.y + value: -453.53 + objectReference: {fileID: 0} + - target: {fileID: 6442521558029674987, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalScale.x + value: 1.1855999 + objectReference: {fileID: 0} + - target: {fileID: 6442521558029674987, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalScale.y + value: 1.1855999 + objectReference: {fileID: 0} + - target: {fileID: 6442521558029674987, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalScale.z + value: 1.1855999 + objectReference: {fileID: 0} + - target: {fileID: 6442521558029674987, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalPosition.z + value: 0.012025 + objectReference: {fileID: 0} + - target: {fileID: 6442521558029674987, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_AnchoredPosition.x + value: 2197.5 + objectReference: {fileID: 0} + - target: {fileID: 6442521558029674987, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_AnchoredPosition.y + value: -453.53 + objectReference: {fileID: 0} + - target: {fileID: 6442521558201973977, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalScale.x + value: 1.1856 + objectReference: {fileID: 0} + - target: {fileID: 6442521558201973977, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalScale.y + value: 1.1856 + objectReference: {fileID: 0} + - target: {fileID: 6442521558201973977, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalScale.z + value: 1.1856 + objectReference: {fileID: 0} + - target: {fileID: 6442521558201973977, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalPosition.z + value: 0.012025 + objectReference: {fileID: 0} + - target: {fileID: 6442521558201973977, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_AnchoredPosition.x + value: 19.559937 + objectReference: {fileID: 0} + - target: {fileID: 6442521558201973977, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_AnchoredPosition.y + value: 186.71 + objectReference: {fileID: 0} + - target: {fileID: 6442521558266236666, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalScale.x + value: 1.1855999 + objectReference: {fileID: 0} + - target: {fileID: 6442521558266236666, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalScale.y + value: 1.1855999 + objectReference: {fileID: 0} + - target: {fileID: 6442521558266236666, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalScale.z + value: 1.1855999 + objectReference: {fileID: 0} + - target: {fileID: 6442521558266236666, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalPosition.z + value: 0.012025 + objectReference: {fileID: 0} + - target: {fileID: 6442521558266236666, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_AnchoredPosition.x + value: 1882 + objectReference: {fileID: 0} + - target: {fileID: 6442521558266236666, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_AnchoredPosition.y + value: -28 + objectReference: {fileID: 0} + - target: {fileID: 6442521558379257519, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalScale.x + value: 1.1855999 + objectReference: {fileID: 0} + - target: {fileID: 6442521558379257519, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalScale.y + value: 1.1855999 + objectReference: {fileID: 0} + - target: {fileID: 6442521558379257519, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalScale.z + value: 1.1855999 + objectReference: {fileID: 0} + - target: {fileID: 6442521558379257519, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalPosition.z + value: 0.012025 + objectReference: {fileID: 0} + - target: {fileID: 6442521558379257519, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_AnchoredPosition.x + value: 19.559937 + objectReference: {fileID: 0} + - target: {fileID: 6442521558379257519, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_AnchoredPosition.y + value: -26.705 + objectReference: {fileID: 0} + - target: {fileID: 6442521558723886156, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalScale.x + value: 1.1855999 + objectReference: {fileID: 0} + - target: {fileID: 6442521558723886156, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalScale.y + value: 1.1855999 + objectReference: {fileID: 0} + - target: {fileID: 6442521558723886156, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalScale.z + value: 1.1855999 + objectReference: {fileID: 0} + - target: {fileID: 6442521558723886156, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalPosition.z + value: 0.012025 + objectReference: {fileID: 0} + - target: {fileID: 6442521558723886156, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_AnchoredPosition.x + value: 1669.8999 + objectReference: {fileID: 0} + - target: {fileID: 6442521558723886156, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_AnchoredPosition.y + value: -241.5 + objectReference: {fileID: 0} + - target: {fileID: 6442521558765767617, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalScale.x + value: 1.1855999 + objectReference: {fileID: 0} + - target: {fileID: 6442521558765767617, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalScale.y + value: 1.1855999 + objectReference: {fileID: 0} + - target: {fileID: 6442521558765767617, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalScale.z + value: 1.1855999 + objectReference: {fileID: 0} + - target: {fileID: 6442521558765767617, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalPosition.z + value: 0.012025 + objectReference: {fileID: 0} + - target: {fileID: 6442521558765767617, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_AnchoredPosition.x + value: 458.23987 + objectReference: {fileID: 0} + - target: {fileID: 6442521558765767617, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_AnchoredPosition.y + value: -453.53 + objectReference: {fileID: 0} + - target: {fileID: 6442521558885621401, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalScale.x + value: 1.1855999 + objectReference: {fileID: 0} + - target: {fileID: 6442521558885621401, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalScale.y + value: 1.1855999 + objectReference: {fileID: 0} + - target: {fileID: 6442521558885621401, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalScale.z + value: 1.1855999 + objectReference: {fileID: 0} + - target: {fileID: 6442521558885621401, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalPosition.z + value: 0.012025 + objectReference: {fileID: 0} + - target: {fileID: 6442521558885621401, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_AnchoredPosition.x + value: 778.36 + objectReference: {fileID: 0} + - target: {fileID: 6442521558885621401, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_AnchoredPosition.y + value: -453.53 + objectReference: {fileID: 0} + - target: {fileID: 6442521559131244628, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalScale.x + value: 1.1855999 + objectReference: {fileID: 0} + - target: {fileID: 6442521559131244628, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalScale.y + value: 1.1855999 + objectReference: {fileID: 0} + - target: {fileID: 6442521559131244628, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalScale.z + value: 1.1855999 + objectReference: {fileID: 0} + - target: {fileID: 6442521559131244628, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalPosition.z + value: 0.012025 + objectReference: {fileID: 0} + - target: {fileID: 6442521559131244628, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_AnchoredPosition.x + value: 2323.1997 + objectReference: {fileID: 0} + - target: {fileID: 6442521559131244628, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_AnchoredPosition.y + value: -240.12 + objectReference: {fileID: 0} + - target: {fileID: 6442521559291037726, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalScale.x + value: 1.1855999 + objectReference: {fileID: 0} + - target: {fileID: 6442521559291037726, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalScale.y + value: 1.1855999 + objectReference: {fileID: 0} + - target: {fileID: 6442521559291037726, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalScale.z + value: 1.1855999 + objectReference: {fileID: 0} + - target: {fileID: 6442521559291037726, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalPosition.z + value: 0.012025 + objectReference: {fileID: 0} + - target: {fileID: 6442521559291037726, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_AnchoredPosition.x + value: 2524.7998 + objectReference: {fileID: 0} + - target: {fileID: 6442521559291037726, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_AnchoredPosition.y + value: -453.53 + objectReference: {fileID: 0} + - target: {fileID: 6442521559422749340, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalScale.x + value: 1.1855999 + objectReference: {fileID: 0} + - target: {fileID: 6442521559422749340, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalScale.y + value: 1.1855999 + objectReference: {fileID: 0} + - target: {fileID: 6442521559422749340, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalScale.z + value: 1.1855999 + objectReference: {fileID: 0} + - target: {fileID: 6442521559422749340, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_LocalPosition.z + value: 0.012025 + objectReference: {fileID: 0} + - target: {fileID: 6442521559422749340, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_AnchoredPosition.x + value: 14.819946 + objectReference: {fileID: 0} + - target: {fileID: 6442521559422749340, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_AnchoredPosition.y + value: -240.12 + objectReference: {fileID: 0} + - target: {fileID: 6516906865040715207, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_IsActive + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6516906865109213156, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_IsActive + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 6516906865272358958, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_IsActive + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6516906865285074865, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_IsActive + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6516906865492943198, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_IsActive + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6516906865735590991, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_IsActive + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6516906865818221851, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_IsActive + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6516906865969425441, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_IsActive + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6516906866017401077, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_IsActive + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6516906866100164864, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_IsActive + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6516906866236365698, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_IsActive + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6516906866242050540, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_IsActive + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6516906866250146616, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_IsActive + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6516906866391513881, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_IsActive + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6516906866427954056, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_IsActive + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6516906866528436670, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_IsActive + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6516906866682539346, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_IsActive + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 6516906866757688031, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_IsActive + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6516906866772971399, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_IsActive + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6516906866851944814, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_IsActive + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6516906867023499934, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_IsActive + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 6516906867081517386, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_IsActive + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 8210763275035622327, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_Text + value: + objectReference: {fileID: 0} + - target: {fileID: 8210763275035622327, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_FontData.m_Font + value: + objectReference: {fileID: 12800000, guid: bdb48149d5b0cf849a1135d87f1b619f, + type: 3} + - target: {fileID: 8210763275035622327, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_FontData.m_MinSize + value: 4 + objectReference: {fileID: 0} + - target: {fileID: 8210763275035622327, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_FontData.m_FontSize + value: 300 + objectReference: {fileID: 0} + - target: {fileID: 8210763275035622327, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + propertyPath: m_FontData.m_Alignment + value: 4 + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: ef7eb6dda2db50c4bbf6c682e4a21736, type: 3} +--- !u!224 &3194813434804236579 stripped +RectTransform: + m_CorrespondingSourceObject: {fileID: 224560323429904302, guid: ef7eb6dda2db50c4bbf6c682e4a21736, + type: 3} + m_PrefabInstance: {fileID: 3407973161605095053} + m_PrefabAsset: {fileID: 0} --- !u!1001 &4530350375719397069 PrefabInstance: m_ObjectHideFlags: 0 serializedVersion: 2 m_Modification: + serializedVersion: 3 m_TransformParent: {fileID: 3576301794080265196} m_Modifications: - target: {fileID: 5108924410514366489, guid: cc0d72d82ebc4604eb11a2b2aae17547, @@ -9824,6 +15055,9 @@ PrefabInstance: value: 0 objectReference: {fileID: 0} m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: cc0d72d82ebc4604eb11a2b2aae17547, type: 3} --- !u!4 &6679582736177907422 stripped Transform: @@ -9842,6 +15076,7 @@ PrefabInstance: m_ObjectHideFlags: 0 serializedVersion: 2 m_Modification: + serializedVersion: 3 m_TransformParent: {fileID: 3576301794080265196} m_Modifications: - target: {fileID: 8058103854604790177, guid: bc0454c142b400c469bd0d54ce226a24, @@ -9905,6 +15140,9 @@ PrefabInstance: value: EnabledElements objectReference: {fileID: 0} m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: bc0454c142b400c469bd0d54ce226a24, type: 3} --- !u!114 &554234529220568430 stripped MonoBehaviour: @@ -9947,6 +15185,7 @@ PrefabInstance: m_ObjectHideFlags: 0 serializedVersion: 2 m_Modification: + serializedVersion: 3 m_TransformParent: {fileID: 3576301794080265196} m_Modifications: - target: {fileID: 229422388496447405, guid: 99a38de63f18d524c91733042928d80a, @@ -10010,6 +15249,9 @@ PrefabInstance: value: DriveFullElements objectReference: {fileID: 0} m_RemovedComponents: [] + m_RemovedGameObjects: [] + m_AddedGameObjects: [] + m_AddedComponents: [] m_SourcePrefab: {fileID: 100100000, guid: 99a38de63f18d524c91733042928d80a, type: 3} --- !u!1 &5684969559238275584 stripped GameObject: diff --git a/Assets/Prefabs/PopUps/PopupWindow_Upload.prefab b/Assets/Prefabs/PopUps/PopupWindow_Upload.prefab index 42b3563b22..d9aaa92820 100644 --- a/Assets/Prefabs/PopUps/PopupWindow_Upload.prefab +++ b/Assets/Prefabs/PopUps/PopupWindow_Upload.prefab @@ -1402,7 +1402,7 @@ GameObject: m_Component: - component: {fileID: 4000013830214004} m_Layer: 16 - m_Name: EmbeddedMediaWarningPoly + m_Name: EmbeddedMediaWarningIcosa m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 @@ -2079,13 +2079,13 @@ MonoBehaviour: m_Progress: {fileID: 23000010967552864} m_LoginOnDesktopObjects: {fileID: 1000013096383082} m_ConfirmObjects: {fileID: 6508589329552276940} - m_PolyLoggedInObjects: {fileID: 2420543688105002897} - m_PolyLoggedOutObjects: {fileID: 587811777206900469} + m_IcosaLoggedInObjects: {fileID: 2420543688105002897} + m_IcosaLoggedOutObjects: {fileID: 587811777206900469} m_SketchfabLoggedInObjects: {fileID: 4035661904903806700} m_SketchfabLoggedOutObjects: {fileID: 5455702764299504055} - m_PolyUserName: {fileID: 5207780760739753065} + m_IcosaUserName: {fileID: 5207780760739753065} m_SketchfabUserName: {fileID: 8355879036552585063} - m_GooglePhoto: {fileID: 5158317984005904495} + m_IcosaPhoto: {fileID: 5158317984005904495} m_SketchfabPhoto: {fileID: 6725221811800815683} m_UploadObjects: {fileID: 1000013114340806} m_UploadCompleteObjects: {fileID: 1000012022869828} @@ -2093,7 +2093,7 @@ MonoBehaviour: m_UploadFailedMessage: {fileID: 114000010005430638} m_UploadingDeniedObjects: {fileID: 1954885538622324} m_WaitObjects: {fileID: 1000010727908878} - m_EmbeddedMediaWarningPoly: {fileID: 1000011947057708} + m_EmbeddedMediaWarningIcosa: {fileID: 1000011947057708} m_EmbeddedMediaWarningSketchfab: {fileID: 8734179732674817566} m_NothingToUploadWarning: {fileID: 1607740331362510216} m_ConnectionErrorObjects: {fileID: 1000012381343644} @@ -3994,7 +3994,7 @@ GameObject: - component: {fileID: 3275547546821622028} - component: {fileID: 6831880153218701541} m_Layer: 16 - m_Name: Poly_Logo + m_Name: Icosa_Logo m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 @@ -4043,7 +4043,7 @@ MeshRenderer: m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 2100000, guid: 7a3b280f73263e34c97f3dd6db616888, type: 2} + - {fileID: 2100000, guid: e7a4b5a3979042447af7f344f59498c7, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 @@ -4543,7 +4543,7 @@ GameObject: m_Component: - component: {fileID: 791103424055215284} m_Layer: 16 - m_Name: Poly_LoggedOutElements + m_Name: Icosa_LoggedOutElements m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 @@ -6497,7 +6497,7 @@ GameObject: m_Component: - component: {fileID: 4248595653238781298} m_Layer: 16 - m_Name: Poly_LoggedInElements + m_Name: Icosa_LoggedInElements m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 @@ -7092,7 +7092,7 @@ MonoBehaviour: m_HoverBoxColliderGrow: 0.05 m_AddOverlay: 0 m_Command: 96 - m_CommandParam: 1 + m_CommandParam: 3 m_CommandParam2: -1 m_RequiresPopup: 0 m_CenterPopupOnButton: 0 @@ -10314,7 +10314,7 @@ MonoBehaviour: m_HoverBoxColliderGrow: 0.05 m_AddOverlay: 0 m_Command: 95 - m_CommandParam: 1 + m_CommandParam: 3 m_CommandParam2: -1 m_RequiresPopup: 0 m_CenterPopupOnButton: 0 @@ -11164,7 +11164,7 @@ GameObject: - component: {fileID: 5387404676713886195} - component: {fileID: 5158317984005904495} m_Layer: 16 - m_Name: Google_ProfilePhoto + m_Name: Icosa_ProfilePhoto m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 @@ -11720,7 +11720,7 @@ MeshRenderer: m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 2100000, guid: 7a3b280f73263e34c97f3dd6db616888, type: 2} + - {fileID: 2100000, guid: e7a4b5a3979042447af7f344f59498c7, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 diff --git a/Assets/Resources/EnvironmentPrefabs/AmbientDust.prefab b/Assets/Resources/EnvironmentPrefabs/AmbientDust.prefab index c08643156b..40a8cedd0d 100644 --- a/Assets/Resources/EnvironmentPrefabs/AmbientDust.prefab +++ b/Assets/Resources/EnvironmentPrefabs/AmbientDust.prefab @@ -9,7 +9,7 @@ GameObject: serializedVersion: 6 m_Component: - component: {fileID: 472934} - m_Layer: 0 + m_Layer: 25 m_Name: AmbientDust m_TagString: Untagged m_Icon: {fileID: 0} @@ -26,6 +26,7 @@ Transform: 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_ConstrainProportionsScale: 0 m_Children: - {fileID: 483582} m_Father: {fileID: 0} @@ -42,7 +43,7 @@ GameObject: - component: {fileID: 483582} - component: {fileID: 19891146} - component: {fileID: 19910528} - m_Layer: 0 + m_Layer: 25 m_Name: AmbientDust m_TagString: Untagged m_Icon: {fileID: 0} @@ -59,6 +60,7 @@ Transform: m_LocalRotation: {x: -0.7071068, y: 0, z: 0, w: 0.7071068} m_LocalPosition: {x: 0, y: 15, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 472934} m_RootOrder: 0 @@ -70,19 +72,19 @@ ParticleSystem: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 119290} - serializedVersion: 6 + serializedVersion: 8 lengthInSec: 5 simulationSpeed: 1 stopAction: 0 cullingMode: 1 ringBufferMode: 0 ringBufferLoopRange: {x: 0, y: 1} + emitterVelocityMode: 0 looping: 1 prewarm: 1 playOnAwake: 1 useUnscaledTime: 0 autoRandomSeed: 1 - useRigidbodyForVelocity: 1 startDelay: serializedVersion: 2 minMaxState: 0 @@ -632,6 +634,7 @@ ParticleSystem: m_RotationOrder: 4 randomizeRotationDirection: 0 maxNumParticles: 1000 + customEmitterVelocity: {x: 0, y: 0, z: 0} size3D: 0 rotation3D: 0 gravityModifier: @@ -1409,6 +1412,7 @@ ParticleSystem: m_NumColorKeys: 2 m_NumAlphaKeys: 2 UVModule: + serializedVersion: 2 enabled: 0 mode: 0 timeMode: 0 @@ -1508,7 +1512,7 @@ ParticleSystem: rowIndex: 0 cycles: 1 uvChannelMask: -1 - randomRow: 1 + rowMode: 1 sprites: - sprite: {fileID: 0} flipU: 0 @@ -2155,6 +2159,62 @@ ParticleSystem: m_PreInfinity: 2 m_PostInfinity: 2 m_RotationOrder: 4 + LifetimeByEmitterSpeedModule: + enabled: 0 + m_Curve: + serializedVersion: 2 + minMaxState: 1 + scalar: 1 + minScalar: 1 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: -0.8 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 0.2 + inSlope: -0.8 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + m_Range: {x: 0, y: 1} ForceModule: enabled: 0 x: @@ -2319,8 +2379,61 @@ ParticleSystem: inWorldSpace: 0 randomizePerFrame: 0 ExternalForcesModule: + serializedVersion: 2 enabled: 0 - multiplier: 1 + multiplierCurve: + serializedVersion: 2 + minMaxState: 0 + scalar: 1 + minScalar: 1 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 influenceFilter: 0 influenceMask: serializedVersion: 2 @@ -3532,19 +3645,20 @@ ParticleSystem: range: {x: 0, y: 1} CollisionModule: enabled: 0 - serializedVersion: 3 + serializedVersion: 4 type: 0 collisionMode: 0 colliderForce: 0 multiplyColliderForceByParticleSize: 0 multiplyColliderForceByParticleSpeed: 0 multiplyColliderForceByCollisionAngle: 1 - plane0: {fileID: 0} - plane1: {fileID: 0} - plane2: {fileID: 0} - plane3: {fileID: 0} - plane4: {fileID: 0} - plane5: {fileID: 0} + m_Planes: + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} m_Dampen: serializedVersion: 2 minMaxState: 0 @@ -3718,17 +3832,20 @@ ParticleSystem: interiorCollisions: 1 TriggerModule: enabled: 0 - collisionShape0: {fileID: 0} - collisionShape1: {fileID: 0} - collisionShape2: {fileID: 0} - collisionShape3: {fileID: 0} - collisionShape4: {fileID: 0} - collisionShape5: {fileID: 0} + serializedVersion: 2 inside: 1 outside: 0 enter: 0 exit: 0 + colliderQueryMode: 0 radiusScale: 1 + primitives: + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} SubModule: serializedVersion: 2 enabled: 0 @@ -4679,9 +4796,12 @@ ParticleSystemRenderer: m_CastShadows: 1 m_ReceiveShadows: 1 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 + m_RayTracingMode: 0 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -4694,6 +4814,7 @@ ParticleSystemRenderer: m_ProbeAnchor: {fileID: 0} m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 + m_ReceiveGI: 1 m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 @@ -4707,6 +4828,7 @@ ParticleSystemRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_RenderMode: 0 + m_MeshDistribution: 0 m_SortMode: 0 m_MinParticleSize: 0 m_MaxParticleSize: 0.5 @@ -4723,9 +4845,15 @@ ParticleSystemRenderer: m_EnableGPUInstancing: 0 m_ApplyActiveColorSpace: 0 m_AllowRoll: 1 + m_FreeformStretching: 0 + m_RotateWithStretchDirection: 1 m_VertexStreams: 0001030405 m_Mesh: {fileID: 0} m_Mesh1: {fileID: 0} m_Mesh2: {fileID: 0} m_Mesh3: {fileID: 0} + m_MeshWeighting: 1 + m_MeshWeighting1: 1 + m_MeshWeighting2: 1 + m_MeshWeighting3: 1 m_MaskInteraction: 0 diff --git a/Assets/Resources/EnvironmentPrefabs/AmbientDustDim.prefab b/Assets/Resources/EnvironmentPrefabs/AmbientDustDim.prefab index 8945aa7c80..4ad1dbfc8f 100644 --- a/Assets/Resources/EnvironmentPrefabs/AmbientDustDim.prefab +++ b/Assets/Resources/EnvironmentPrefabs/AmbientDustDim.prefab @@ -9,7 +9,7 @@ GameObject: serializedVersion: 6 m_Component: - component: {fileID: 472934} - m_Layer: 0 + m_Layer: 25 m_Name: AmbientDustDim m_TagString: Untagged m_Icon: {fileID: 0} @@ -26,6 +26,7 @@ Transform: 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_ConstrainProportionsScale: 0 m_Children: - {fileID: 427470} m_Father: {fileID: 0} @@ -42,7 +43,7 @@ GameObject: - component: {fileID: 427470} - component: {fileID: 19846126} - component: {fileID: 19992888} - m_Layer: 0 + m_Layer: 25 m_Name: AmbientDustDim m_TagString: Untagged m_Icon: {fileID: 0} @@ -59,6 +60,7 @@ Transform: m_LocalRotation: {x: -0.7071068, y: 0, z: 0, w: 0.7071068} m_LocalPosition: {x: 0, y: 15, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 472934} m_RootOrder: 0 @@ -70,19 +72,19 @@ ParticleSystem: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 124756} - serializedVersion: 6 + serializedVersion: 8 lengthInSec: 5 simulationSpeed: 1 stopAction: 0 cullingMode: 1 ringBufferMode: 0 ringBufferLoopRange: {x: 0, y: 1} + emitterVelocityMode: 0 looping: 1 prewarm: 1 playOnAwake: 1 useUnscaledTime: 0 autoRandomSeed: 1 - useRigidbodyForVelocity: 1 startDelay: serializedVersion: 2 minMaxState: 0 @@ -632,6 +634,7 @@ ParticleSystem: m_RotationOrder: 4 randomizeRotationDirection: 0 maxNumParticles: 1000 + customEmitterVelocity: {x: 0, y: 0, z: 0} size3D: 0 rotation3D: 0 gravityModifier: @@ -1409,6 +1412,7 @@ ParticleSystem: m_NumColorKeys: 2 m_NumAlphaKeys: 2 UVModule: + serializedVersion: 2 enabled: 0 mode: 0 timeMode: 0 @@ -1508,7 +1512,7 @@ ParticleSystem: rowIndex: 0 cycles: 1 uvChannelMask: -1 - randomRow: 1 + rowMode: 1 sprites: - sprite: {fileID: 0} flipU: 0 @@ -2155,6 +2159,62 @@ ParticleSystem: m_PreInfinity: 2 m_PostInfinity: 2 m_RotationOrder: 4 + LifetimeByEmitterSpeedModule: + enabled: 0 + m_Curve: + serializedVersion: 2 + minMaxState: 1 + scalar: 1 + minScalar: 1 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: -0.8 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 0.2 + inSlope: -0.8 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + m_Range: {x: 0, y: 1} ForceModule: enabled: 0 x: @@ -2319,8 +2379,61 @@ ParticleSystem: inWorldSpace: 0 randomizePerFrame: 0 ExternalForcesModule: + serializedVersion: 2 enabled: 0 - multiplier: 1 + multiplierCurve: + serializedVersion: 2 + minMaxState: 0 + scalar: 1 + minScalar: 1 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 influenceFilter: 0 influenceMask: serializedVersion: 2 @@ -3532,19 +3645,20 @@ ParticleSystem: range: {x: 0, y: 1} CollisionModule: enabled: 0 - serializedVersion: 3 + serializedVersion: 4 type: 0 collisionMode: 0 colliderForce: 0 multiplyColliderForceByParticleSize: 0 multiplyColliderForceByParticleSpeed: 0 multiplyColliderForceByCollisionAngle: 1 - plane0: {fileID: 0} - plane1: {fileID: 0} - plane2: {fileID: 0} - plane3: {fileID: 0} - plane4: {fileID: 0} - plane5: {fileID: 0} + m_Planes: + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} m_Dampen: serializedVersion: 2 minMaxState: 0 @@ -3718,17 +3832,20 @@ ParticleSystem: interiorCollisions: 1 TriggerModule: enabled: 0 - collisionShape0: {fileID: 0} - collisionShape1: {fileID: 0} - collisionShape2: {fileID: 0} - collisionShape3: {fileID: 0} - collisionShape4: {fileID: 0} - collisionShape5: {fileID: 0} + serializedVersion: 2 inside: 1 outside: 0 enter: 0 exit: 0 + colliderQueryMode: 0 radiusScale: 1 + primitives: + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} SubModule: serializedVersion: 2 enabled: 0 @@ -4679,9 +4796,12 @@ ParticleSystemRenderer: m_CastShadows: 1 m_ReceiveShadows: 1 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 + m_RayTracingMode: 0 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -4694,6 +4814,7 @@ ParticleSystemRenderer: m_ProbeAnchor: {fileID: 0} m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 + m_ReceiveGI: 1 m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 @@ -4707,6 +4828,7 @@ ParticleSystemRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_RenderMode: 0 + m_MeshDistribution: 0 m_SortMode: 0 m_MinParticleSize: 0 m_MaxParticleSize: 0.5 @@ -4723,9 +4845,15 @@ ParticleSystemRenderer: m_EnableGPUInstancing: 0 m_ApplyActiveColorSpace: 0 m_AllowRoll: 1 + m_FreeformStretching: 0 + m_RotateWithStretchDirection: 1 m_VertexStreams: 0001030405 m_Mesh: {fileID: 0} m_Mesh1: {fileID: 0} m_Mesh2: {fileID: 0} m_Mesh3: {fileID: 0} + m_MeshWeighting: 1 + m_MeshWeighting1: 1 + m_MeshWeighting2: 1 + m_MeshWeighting3: 1 m_MaskInteraction: 0 diff --git a/Assets/Resources/EnvironmentPrefabs/AmbientGrid.prefab b/Assets/Resources/EnvironmentPrefabs/AmbientGrid.prefab index 7f2b081426..070364abce 100644 --- a/Assets/Resources/EnvironmentPrefabs/AmbientGrid.prefab +++ b/Assets/Resources/EnvironmentPrefabs/AmbientGrid.prefab @@ -11,7 +11,7 @@ GameObject: - component: {fileID: 441654} - component: {fileID: 3328860} - component: {fileID: 2387148} - m_Layer: 0 + m_Layer: 25 m_Name: AmbientGrid m_TagString: Untagged m_Icon: {fileID: 0} @@ -28,6 +28,7 @@ Transform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 5.3, y: 5, z: -40} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 462152} m_RootOrder: 0 @@ -51,9 +52,12 @@ MeshRenderer: m_CastShadows: 0 m_ReceiveShadows: 0 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 0 m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -65,6 +69,7 @@ MeshRenderer: m_ProbeAnchor: {fileID: 0} m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 + m_ReceiveGI: 1 m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 @@ -77,6 +82,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!1 &117590 GameObject: m_ObjectHideFlags: 0 @@ -86,7 +92,7 @@ GameObject: serializedVersion: 6 m_Component: - component: {fileID: 455556} - m_Layer: 0 + m_Layer: 25 m_Name: AmbientGridAudio m_TagString: Untagged m_Icon: {fileID: 0} @@ -103,6 +109,7 @@ Transform: 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_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 426446} m_RootOrder: 0 @@ -117,7 +124,7 @@ GameObject: m_Component: - component: {fileID: 417594} - component: {fileID: 114616253018658896} - m_Layer: 0 + m_Layer: 25 m_Name: AmbientGridSmall m_TagString: Untagged m_Icon: {fileID: 0} @@ -134,6 +141,7 @@ Transform: 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.5, z: 0.5} + m_ConstrainProportionsScale: 0 m_Children: - {fileID: 435688} m_Father: {fileID: 426446} @@ -164,7 +172,7 @@ GameObject: m_Component: - component: {fileID: 426446} - component: {fileID: 11449142} - m_Layer: 0 + m_Layer: 25 m_Name: AmbientGrid m_TagString: Untagged m_Icon: {fileID: 0} @@ -181,6 +189,7 @@ Transform: 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_ConstrainProportionsScale: 0 m_Children: - {fileID: 455556} - {fileID: 462152} @@ -215,7 +224,7 @@ GameObject: - component: {fileID: 435688} - component: {fileID: 3364224} - component: {fileID: 2389974} - m_Layer: 0 + m_Layer: 25 m_Name: AmbientGrid m_TagString: Untagged m_Icon: {fileID: 0} @@ -232,6 +241,7 @@ Transform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 5.3, y: 5, z: -40} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 417594} m_RootOrder: 0 @@ -255,9 +265,12 @@ MeshRenderer: m_CastShadows: 0 m_ReceiveShadows: 0 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 0 m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -269,6 +282,7 @@ MeshRenderer: m_ProbeAnchor: {fileID: 0} m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 + m_ReceiveGI: 1 m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 @@ -281,6 +295,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!1 &185908 GameObject: m_ObjectHideFlags: 0 @@ -291,7 +306,7 @@ GameObject: m_Component: - component: {fileID: 462152} - component: {fileID: 114356150969872122} - m_Layer: 0 + m_Layer: 25 m_Name: AmbientGridBig m_TagString: Untagged m_Icon: {fileID: 0} @@ -308,6 +323,7 @@ Transform: 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_ConstrainProportionsScale: 0 m_Children: - {fileID: 441654} m_Father: {fileID: 426446} diff --git a/Assets/Resources/EnvironmentPrefabs/AmbientGrid_Blue.prefab b/Assets/Resources/EnvironmentPrefabs/AmbientGrid_Blue.prefab index 050938b9d6..7bc8a56147 100644 --- a/Assets/Resources/EnvironmentPrefabs/AmbientGrid_Blue.prefab +++ b/Assets/Resources/EnvironmentPrefabs/AmbientGrid_Blue.prefab @@ -9,7 +9,7 @@ GameObject: serializedVersion: 6 m_Component: - component: {fileID: 411922} - m_Layer: 0 + m_Layer: 25 m_Name: AmbientGridAudio m_TagString: Untagged m_Icon: {fileID: 0} @@ -26,6 +26,7 @@ Transform: 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_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 426446} m_RootOrder: 0 @@ -41,7 +42,7 @@ GameObject: - component: {fileID: 416930} - component: {fileID: 3382168} - component: {fileID: 2355276} - m_Layer: 0 + m_Layer: 25 m_Name: AmbientGrid m_TagString: Untagged m_Icon: {fileID: 0} @@ -58,6 +59,7 @@ Transform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 5.3, y: 5, z: -40} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 452114} m_RootOrder: 0 @@ -81,9 +83,12 @@ MeshRenderer: m_CastShadows: 0 m_ReceiveShadows: 0 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 0 m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -95,6 +100,7 @@ MeshRenderer: m_ProbeAnchor: {fileID: 0} m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 + m_ReceiveGI: 1 m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 @@ -107,6 +113,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!1 &146818 GameObject: m_ObjectHideFlags: 0 @@ -117,7 +124,7 @@ GameObject: m_Component: - component: {fileID: 426446} - component: {fileID: 11475594} - m_Layer: 0 + m_Layer: 25 m_Name: AmbientGrid_Blue m_TagString: Untagged m_Icon: {fileID: 0} @@ -134,6 +141,7 @@ Transform: 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_ConstrainProportionsScale: 0 m_Children: - {fileID: 411922} - {fileID: 424610} @@ -168,7 +176,7 @@ GameObject: - component: {fileID: 436200} - component: {fileID: 3327902} - component: {fileID: 2365078} - m_Layer: 0 + m_Layer: 25 m_Name: AmbientGrid m_TagString: Untagged m_Icon: {fileID: 0} @@ -185,6 +193,7 @@ Transform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 5.3, y: 5, z: -40} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 424610} m_RootOrder: 0 @@ -208,9 +217,12 @@ MeshRenderer: m_CastShadows: 0 m_ReceiveShadows: 0 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 0 m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -222,6 +234,7 @@ MeshRenderer: m_ProbeAnchor: {fileID: 0} m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 + m_ReceiveGI: 1 m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 @@ -234,6 +247,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!1 &182776 GameObject: m_ObjectHideFlags: 0 @@ -244,7 +258,7 @@ GameObject: m_Component: - component: {fileID: 424610} - component: {fileID: 114430266970355340} - m_Layer: 0 + m_Layer: 25 m_Name: AmbientGridBig m_TagString: Untagged m_Icon: {fileID: 0} @@ -261,6 +275,7 @@ Transform: 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_ConstrainProportionsScale: 0 m_Children: - {fileID: 436200} m_Father: {fileID: 426446} @@ -291,7 +306,7 @@ GameObject: m_Component: - component: {fileID: 452114} - component: {fileID: 114719356951609022} - m_Layer: 0 + m_Layer: 25 m_Name: AmbientGridSmall m_TagString: Untagged m_Icon: {fileID: 0} @@ -308,6 +323,7 @@ Transform: 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.5, z: 0.5} + m_ConstrainProportionsScale: 0 m_Children: - {fileID: 416930} m_Father: {fileID: 426446} diff --git a/Assets/Resources/EnvironmentPrefabs/DressForm.prefab b/Assets/Resources/EnvironmentPrefabs/DressForm.prefab index 718a0bdd5e..9536e0b258 100644 --- a/Assets/Resources/EnvironmentPrefabs/DressForm.prefab +++ b/Assets/Resources/EnvironmentPrefabs/DressForm.prefab @@ -9,7 +9,7 @@ GameObject: serializedVersion: 6 m_Component: - component: {fileID: 455888} - m_Layer: 0 + m_Layer: 25 m_Name: DressFormModel m_TagString: Untagged m_Icon: {fileID: 0} @@ -26,6 +26,7 @@ Transform: m_LocalRotation: {x: 0, y: -1, z: 0, w: -0.00000016292068} m_LocalPosition: {x: 0, y: 0, z: 5} m_LocalScale: {x: 0.10808116, y: 0.105000004, z: 0.108081155} + m_ConstrainProportionsScale: 0 m_Children: - {fileID: 410190} - {fileID: 471872} @@ -43,7 +44,7 @@ GameObject: - component: {fileID: 447284} - component: {fileID: 3377986} - component: {fileID: 2320842} - m_Layer: 0 + m_Layer: 25 m_Name: GroundUnderside m_TagString: Untagged m_Icon: {fileID: 0} @@ -60,6 +61,7 @@ Transform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: -0.5, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 438498} m_RootOrder: 7 @@ -83,9 +85,12 @@ MeshRenderer: m_CastShadows: 1 m_ReceiveShadows: 1 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -97,6 +102,7 @@ MeshRenderer: m_ProbeAnchor: {fileID: 0} m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 + m_ReceiveGI: 1 m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 @@ -109,6 +115,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!1 &116648 GameObject: m_ObjectHideFlags: 0 @@ -120,7 +127,7 @@ GameObject: - component: {fileID: 469106} - component: {fileID: 3360860} - component: {fileID: 2365230} - m_Layer: 0 + m_Layer: 25 m_Name: Geo_FloorBackground m_TagString: Untagged m_Icon: {fileID: 0} @@ -137,6 +144,7 @@ Transform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: -0, y: -0.5, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 438498} m_RootOrder: 0 @@ -160,9 +168,12 @@ MeshRenderer: m_CastShadows: 0 m_ReceiveShadows: 0 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -174,6 +185,7 @@ MeshRenderer: m_ProbeAnchor: {fileID: 0} m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 + m_ReceiveGI: 1 m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 @@ -186,6 +198,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!1 &128170 GameObject: m_ObjectHideFlags: 0 @@ -197,7 +210,7 @@ GameObject: - component: {fileID: 476664} - component: {fileID: 3344320} - component: {fileID: 2395968} - m_Layer: 0 + m_Layer: 25 m_Name: Geo_FloorForeground m_TagString: Untagged m_Icon: {fileID: 0} @@ -214,6 +227,7 @@ Transform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: -0, y: -0.25, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 438498} m_RootOrder: 1 @@ -237,9 +251,12 @@ MeshRenderer: m_CastShadows: 0 m_ReceiveShadows: 1 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -251,6 +268,7 @@ MeshRenderer: m_ProbeAnchor: {fileID: 0} m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 + m_ReceiveGI: 1 m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 @@ -263,6 +281,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!1 &139798 GameObject: m_ObjectHideFlags: 0 @@ -274,7 +293,7 @@ GameObject: - component: {fileID: 446564} - component: {fileID: 3356250} - component: {fileID: 2381768} - m_Layer: 0 + m_Layer: 25 m_Name: Geo_PropStage m_TagString: Untagged m_Icon: {fileID: 0} @@ -291,6 +310,7 @@ Transform: m_LocalRotation: {x: 0, y: 1, z: 0, w: 0} m_LocalPosition: {x: 0, y: -0.25, z: 0} m_LocalScale: {x: 3, y: 0.05, z: 3} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 438498} m_RootOrder: 5 @@ -314,9 +334,12 @@ MeshRenderer: m_CastShadows: 1 m_ReceiveShadows: 1 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -328,6 +351,7 @@ MeshRenderer: m_ProbeAnchor: {fileID: 0} m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 + m_ReceiveGI: 1 m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 @@ -340,6 +364,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!1 &144802 GameObject: m_ObjectHideFlags: 0 @@ -352,7 +377,7 @@ GameObject: - component: {fileID: 3347644} - component: {fileID: 2317444} - component: {fileID: 114652373354654332} - m_Layer: 0 + m_Layer: 25 m_Name: GroundDisk m_TagString: Untagged m_Icon: {fileID: 0} @@ -369,6 +394,7 @@ Transform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: -0.5, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 438498} m_RootOrder: 6 @@ -392,9 +418,12 @@ MeshRenderer: m_CastShadows: 0 m_ReceiveShadows: 0 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -406,6 +435,7 @@ MeshRenderer: m_ProbeAnchor: {fileID: 0} m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 + m_ReceiveGI: 1 m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 @@ -418,6 +448,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!114 &114652373354654332 MonoBehaviour: m_ObjectHideFlags: 0 @@ -442,7 +473,7 @@ GameObject: serializedVersion: 6 m_Component: - component: {fileID: 438498} - m_Layer: 0 + m_Layer: 25 m_Name: DressForm m_TagString: Untagged m_Icon: {fileID: 0} @@ -459,6 +490,7 @@ Transform: 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_ConstrainProportionsScale: 0 m_Children: - {fileID: 469106} - {fileID: 476664} @@ -483,7 +515,7 @@ GameObject: - component: {fileID: 19891870} - component: {fileID: 19940258} - component: {fileID: 114392821061360260} - m_Layer: 0 + m_Layer: 25 m_Name: DustMotes m_TagString: Untagged m_Icon: {fileID: 0} @@ -500,6 +532,7 @@ Transform: m_LocalRotation: {x: -0.7071068, y: 0, z: 0, w: 0.7071068} m_LocalPosition: {x: 0, y: 15, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 438498} m_RootOrder: 3 @@ -511,19 +544,19 @@ ParticleSystem: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 159002} - serializedVersion: 6 + serializedVersion: 8 lengthInSec: 5 simulationSpeed: 1 stopAction: 0 cullingMode: 1 ringBufferMode: 0 ringBufferLoopRange: {x: 0, y: 1} + emitterVelocityMode: 0 looping: 1 prewarm: 1 playOnAwake: 1 useUnscaledTime: 0 autoRandomSeed: 1 - useRigidbodyForVelocity: 1 startDelay: serializedVersion: 2 minMaxState: 0 @@ -1073,6 +1106,7 @@ ParticleSystem: m_RotationOrder: 4 randomizeRotationDirection: 0 maxNumParticles: 1000 + customEmitterVelocity: {x: 0, y: 0, z: 0} size3D: 0 rotation3D: 0 gravityModifier: @@ -1850,6 +1884,7 @@ ParticleSystem: m_NumColorKeys: 2 m_NumAlphaKeys: 2 UVModule: + serializedVersion: 2 enabled: 0 mode: 0 timeMode: 0 @@ -1949,7 +1984,7 @@ ParticleSystem: rowIndex: 0 cycles: 1 uvChannelMask: -1 - randomRow: 1 + rowMode: 1 sprites: - sprite: {fileID: 0} flipU: 0 @@ -2596,6 +2631,62 @@ ParticleSystem: m_PreInfinity: 2 m_PostInfinity: 2 m_RotationOrder: 4 + LifetimeByEmitterSpeedModule: + enabled: 0 + m_Curve: + serializedVersion: 2 + minMaxState: 1 + scalar: 1 + minScalar: 1 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: -0.8 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 0.2 + inSlope: -0.8 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + m_Range: {x: 0, y: 1} ForceModule: enabled: 0 x: @@ -2760,8 +2851,61 @@ ParticleSystem: inWorldSpace: 0 randomizePerFrame: 0 ExternalForcesModule: + serializedVersion: 2 enabled: 0 - multiplier: 1 + multiplierCurve: + serializedVersion: 2 + minMaxState: 0 + scalar: 1 + minScalar: 1 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 influenceFilter: 0 influenceMask: serializedVersion: 2 @@ -3973,19 +4117,20 @@ ParticleSystem: range: {x: 0, y: 1} CollisionModule: enabled: 0 - serializedVersion: 3 + serializedVersion: 4 type: 0 collisionMode: 0 colliderForce: 0 multiplyColliderForceByParticleSize: 0 multiplyColliderForceByParticleSpeed: 0 multiplyColliderForceByCollisionAngle: 1 - plane0: {fileID: 0} - plane1: {fileID: 0} - plane2: {fileID: 0} - plane3: {fileID: 0} - plane4: {fileID: 0} - plane5: {fileID: 0} + m_Planes: + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} m_Dampen: serializedVersion: 2 minMaxState: 0 @@ -4159,17 +4304,20 @@ ParticleSystem: interiorCollisions: 1 TriggerModule: enabled: 0 - collisionShape0: {fileID: 0} - collisionShape1: {fileID: 0} - collisionShape2: {fileID: 0} - collisionShape3: {fileID: 0} - collisionShape4: {fileID: 0} - collisionShape5: {fileID: 0} + serializedVersion: 2 inside: 1 outside: 0 enter: 0 exit: 0 + colliderQueryMode: 0 radiusScale: 1 + primitives: + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} SubModule: serializedVersion: 2 enabled: 0 @@ -5120,9 +5268,12 @@ ParticleSystemRenderer: m_CastShadows: 1 m_ReceiveShadows: 1 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 + m_RayTracingMode: 0 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -5135,6 +5286,7 @@ ParticleSystemRenderer: m_ProbeAnchor: {fileID: 0} m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 + m_ReceiveGI: 1 m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 @@ -5148,6 +5300,7 @@ ParticleSystemRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_RenderMode: 0 + m_MeshDistribution: 0 m_SortMode: 0 m_MinParticleSize: 0 m_MaxParticleSize: 0.5 @@ -5164,11 +5317,17 @@ ParticleSystemRenderer: m_EnableGPUInstancing: 0 m_ApplyActiveColorSpace: 0 m_AllowRoll: 1 + m_FreeformStretching: 0 + m_RotateWithStretchDirection: 1 m_VertexStreams: 0001030405 m_Mesh: {fileID: 0} m_Mesh1: {fileID: 0} m_Mesh2: {fileID: 0} m_Mesh3: {fileID: 0} + m_MeshWeighting: 1 + m_MeshWeighting1: 1 + m_MeshWeighting2: 1 + m_MeshWeighting3: 1 m_MaskInteraction: 0 --- !u!114 &114392821061360260 MonoBehaviour: @@ -5196,7 +5355,7 @@ GameObject: - component: {fileID: 410190} - component: {fileID: 3318808} - component: {fileID: 2387822} - m_Layer: 0 + m_Layer: 25 m_Name: Geo_Form m_TagString: Untagged m_Icon: {fileID: 0} @@ -5213,6 +5372,7 @@ Transform: m_LocalRotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071068} m_LocalPosition: {x: -0.051350594, y: 114.1456, z: -0.86714983} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 455888} m_RootOrder: 0 @@ -5236,9 +5396,12 @@ MeshRenderer: m_CastShadows: 1 m_ReceiveShadows: 1 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -5250,6 +5413,7 @@ MeshRenderer: m_ProbeAnchor: {fileID: 0} m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 + m_ReceiveGI: 1 m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 @@ -5262,6 +5426,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!1 &184902 GameObject: m_ObjectHideFlags: 0 @@ -5273,7 +5438,7 @@ GameObject: - component: {fileID: 471872} - component: {fileID: 3313096} - component: {fileID: 2354034} - m_Layer: 0 + m_Layer: 25 m_Name: Geo_Metal m_TagString: Untagged m_Icon: {fileID: 0} @@ -5290,6 +5455,7 @@ Transform: 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_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 455888} m_RootOrder: 1 @@ -5313,9 +5479,12 @@ MeshRenderer: m_CastShadows: 1 m_ReceiveShadows: 1 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -5327,6 +5496,7 @@ MeshRenderer: m_ProbeAnchor: {fileID: 0} m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 + m_ReceiveGI: 1 m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 @@ -5339,6 +5509,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!1 &198728 GameObject: m_ObjectHideFlags: 0 @@ -5350,7 +5521,7 @@ GameObject: - component: {fileID: 424542} - component: {fileID: 3365164} - component: {fileID: 2392740} - m_Layer: 0 + m_Layer: 25 m_Name: Geo_Spikes m_TagString: Untagged m_Icon: {fileID: 0} @@ -5367,6 +5538,7 @@ Transform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 0.4, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 438498} m_RootOrder: 4 @@ -5390,9 +5562,12 @@ MeshRenderer: m_CastShadows: 0 m_ReceiveShadows: 0 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -5404,6 +5579,7 @@ MeshRenderer: m_ProbeAnchor: {fileID: 0} m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 + m_ReceiveGI: 1 m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 @@ -5416,3 +5592,4 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} diff --git a/Assets/Resources/EnvironmentPrefabs/NightSky.prefab b/Assets/Resources/EnvironmentPrefabs/NightSky.prefab index 89500ece77..747fa48da0 100644 --- a/Assets/Resources/EnvironmentPrefabs/NightSky.prefab +++ b/Assets/Resources/EnvironmentPrefabs/NightSky.prefab @@ -11,7 +11,7 @@ GameObject: - component: {fileID: 485358} - component: {fileID: 3392822} - component: {fileID: 2357274} - m_Layer: 0 + m_Layer: 25 m_Name: GroundUnderside m_TagString: Untagged m_Icon: {fileID: 0} @@ -28,6 +28,7 @@ Transform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: -0.5, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 413308} m_RootOrder: 6 @@ -51,9 +52,12 @@ MeshRenderer: m_CastShadows: 1 m_ReceiveShadows: 1 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -65,6 +69,7 @@ MeshRenderer: m_ProbeAnchor: {fileID: 0} m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 + m_ReceiveGI: 1 m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 @@ -77,6 +82,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!1 &118014 GameObject: m_ObjectHideFlags: 0 @@ -88,7 +94,7 @@ GameObject: - component: {fileID: 407766} - component: {fileID: 3311484} - component: {fileID: 2395680} - m_Layer: 0 + m_Layer: 25 m_Name: Geo_StandardStage m_TagString: Untagged m_Icon: {fileID: 0} @@ -105,6 +111,7 @@ Transform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: -0.25, z: 0} m_LocalScale: {x: 3, y: 0.05, z: 3} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 413308} m_RootOrder: 4 @@ -128,9 +135,12 @@ MeshRenderer: m_CastShadows: 1 m_ReceiveShadows: 1 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -142,6 +152,7 @@ MeshRenderer: m_ProbeAnchor: {fileID: 0} m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 + m_ReceiveGI: 1 m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 @@ -154,6 +165,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!1 &118944 GameObject: m_ObjectHideFlags: 0 @@ -163,7 +175,7 @@ GameObject: serializedVersion: 6 m_Component: - component: {fileID: 413308} - m_Layer: 0 + m_Layer: 25 m_Name: NightSky m_TagString: Untagged m_Icon: {fileID: 0} @@ -180,6 +192,7 @@ Transform: 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_ConstrainProportionsScale: 0 m_Children: - {fileID: 489614} - {fileID: 419628} @@ -202,7 +215,7 @@ GameObject: - component: {fileID: 489614} - component: {fileID: 3393744} - component: {fileID: 2343648} - m_Layer: 0 + m_Layer: 25 m_Name: Geo_FloorBackground m_TagString: Untagged m_Icon: {fileID: 0} @@ -219,6 +232,7 @@ Transform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: -0, y: -0.5, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 413308} m_RootOrder: 0 @@ -242,9 +256,12 @@ MeshRenderer: m_CastShadows: 0 m_ReceiveShadows: 0 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -256,6 +273,7 @@ MeshRenderer: m_ProbeAnchor: {fileID: 0} m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 + m_ReceiveGI: 1 m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 @@ -268,6 +286,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!1 &148692 GameObject: m_ObjectHideFlags: 0 @@ -279,7 +298,7 @@ GameObject: - component: {fileID: 419628} - component: {fileID: 3316466} - component: {fileID: 2395074} - m_Layer: 0 + m_Layer: 25 m_Name: Geo_FloorForeground m_TagString: Untagged m_Icon: {fileID: 0} @@ -296,6 +315,7 @@ Transform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: -0, y: -0.25, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 413308} m_RootOrder: 1 @@ -319,9 +339,12 @@ MeshRenderer: m_CastShadows: 0 m_ReceiveShadows: 1 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -333,6 +356,7 @@ MeshRenderer: m_ProbeAnchor: {fileID: 0} m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 + m_ReceiveGI: 1 m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 @@ -345,6 +369,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!1 &150074 GameObject: m_ObjectHideFlags: 0 @@ -357,7 +382,7 @@ GameObject: - component: {fileID: 3332994} - component: {fileID: 2376766} - component: {fileID: 114161264784855924} - m_Layer: 0 + m_Layer: 25 m_Name: GroundDisk m_TagString: Untagged m_Icon: {fileID: 0} @@ -374,6 +399,7 @@ Transform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: -0.5, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 413308} m_RootOrder: 5 @@ -397,9 +423,12 @@ MeshRenderer: m_CastShadows: 0 m_ReceiveShadows: 0 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -411,6 +440,7 @@ MeshRenderer: m_ProbeAnchor: {fileID: 0} m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 + m_ReceiveGI: 1 m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 @@ -423,6 +453,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!114 &114161264784855924 MonoBehaviour: m_ObjectHideFlags: 0 @@ -449,7 +480,7 @@ GameObject: - component: {fileID: 438128} - component: {fileID: 3318024} - component: {fileID: 2393344} - m_Layer: 0 + m_Layer: 25 m_Name: Geo_Spikes m_TagString: Untagged m_Icon: {fileID: 0} @@ -466,6 +497,7 @@ Transform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 0.5, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 413308} m_RootOrder: 2 @@ -489,9 +521,12 @@ MeshRenderer: m_CastShadows: 0 m_ReceiveShadows: 0 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -503,6 +538,7 @@ MeshRenderer: m_ProbeAnchor: {fileID: 0} m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 + m_ReceiveGI: 1 m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 @@ -515,6 +551,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!1 &192090 GameObject: m_ObjectHideFlags: 0 @@ -527,7 +564,7 @@ GameObject: - component: {fileID: 19819992} - component: {fileID: 19994808} - component: {fileID: 114322361939089138} - m_Layer: 0 + m_Layer: 25 m_Name: DustMotes m_TagString: Untagged m_Icon: {fileID: 0} @@ -544,6 +581,7 @@ Transform: m_LocalRotation: {x: -0.7071068, y: 0, z: 0, w: 0.7071068} m_LocalPosition: {x: 0, y: 15, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 413308} m_RootOrder: 3 @@ -555,19 +593,19 @@ ParticleSystem: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 192090} - serializedVersion: 6 + serializedVersion: 8 lengthInSec: 5 simulationSpeed: 1 stopAction: 0 cullingMode: 1 ringBufferMode: 0 ringBufferLoopRange: {x: 0, y: 1} + emitterVelocityMode: 0 looping: 1 prewarm: 1 playOnAwake: 1 useUnscaledTime: 0 autoRandomSeed: 1 - useRigidbodyForVelocity: 1 startDelay: serializedVersion: 2 minMaxState: 0 @@ -1117,6 +1155,7 @@ ParticleSystem: m_RotationOrder: 4 randomizeRotationDirection: 0 maxNumParticles: 1000 + customEmitterVelocity: {x: 0, y: 0, z: 0} size3D: 0 rotation3D: 0 gravityModifier: @@ -1894,6 +1933,7 @@ ParticleSystem: m_NumColorKeys: 2 m_NumAlphaKeys: 2 UVModule: + serializedVersion: 2 enabled: 0 mode: 0 timeMode: 0 @@ -1993,7 +2033,7 @@ ParticleSystem: rowIndex: 0 cycles: 1 uvChannelMask: -1 - randomRow: 1 + rowMode: 1 sprites: - sprite: {fileID: 0} flipU: 0 @@ -2640,6 +2680,62 @@ ParticleSystem: m_PreInfinity: 2 m_PostInfinity: 2 m_RotationOrder: 4 + LifetimeByEmitterSpeedModule: + enabled: 0 + m_Curve: + serializedVersion: 2 + minMaxState: 1 + scalar: 1 + minScalar: 1 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: -0.8 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 0.2 + inSlope: -0.8 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + m_Range: {x: 0, y: 1} ForceModule: enabled: 0 x: @@ -2804,8 +2900,61 @@ ParticleSystem: inWorldSpace: 0 randomizePerFrame: 0 ExternalForcesModule: + serializedVersion: 2 enabled: 0 - multiplier: 1 + multiplierCurve: + serializedVersion: 2 + minMaxState: 0 + scalar: 1 + minScalar: 1 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 influenceFilter: 0 influenceMask: serializedVersion: 2 @@ -4017,19 +4166,20 @@ ParticleSystem: range: {x: 0, y: 1} CollisionModule: enabled: 0 - serializedVersion: 3 + serializedVersion: 4 type: 0 collisionMode: 0 colliderForce: 0 multiplyColliderForceByParticleSize: 0 multiplyColliderForceByParticleSpeed: 0 multiplyColliderForceByCollisionAngle: 1 - plane0: {fileID: 0} - plane1: {fileID: 0} - plane2: {fileID: 0} - plane3: {fileID: 0} - plane4: {fileID: 0} - plane5: {fileID: 0} + m_Planes: + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} m_Dampen: serializedVersion: 2 minMaxState: 0 @@ -4203,17 +4353,20 @@ ParticleSystem: interiorCollisions: 1 TriggerModule: enabled: 0 - collisionShape0: {fileID: 0} - collisionShape1: {fileID: 0} - collisionShape2: {fileID: 0} - collisionShape3: {fileID: 0} - collisionShape4: {fileID: 0} - collisionShape5: {fileID: 0} + serializedVersion: 2 inside: 1 outside: 0 enter: 0 exit: 0 + colliderQueryMode: 0 radiusScale: 1 + primitives: + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} SubModule: serializedVersion: 2 enabled: 0 @@ -5164,9 +5317,12 @@ ParticleSystemRenderer: m_CastShadows: 1 m_ReceiveShadows: 1 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 + m_RayTracingMode: 0 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -5179,6 +5335,7 @@ ParticleSystemRenderer: m_ProbeAnchor: {fileID: 0} m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 + m_ReceiveGI: 1 m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 @@ -5192,6 +5349,7 @@ ParticleSystemRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_RenderMode: 0 + m_MeshDistribution: 0 m_SortMode: 0 m_MinParticleSize: 0 m_MaxParticleSize: 0.5 @@ -5208,11 +5366,17 @@ ParticleSystemRenderer: m_EnableGPUInstancing: 0 m_ApplyActiveColorSpace: 0 m_AllowRoll: 1 + m_FreeformStretching: 0 + m_RotateWithStretchDirection: 1 m_VertexStreams: 0001030405 m_Mesh: {fileID: 0} m_Mesh1: {fileID: 0} m_Mesh2: {fileID: 0} m_Mesh3: {fileID: 0} + m_MeshWeighting: 1 + m_MeshWeighting1: 1 + m_MeshWeighting2: 1 + m_MeshWeighting3: 1 m_MaskInteraction: 0 --- !u!114 &114322361939089138 MonoBehaviour: diff --git a/Assets/Resources/EnvironmentPrefabs/Pedestal.prefab b/Assets/Resources/EnvironmentPrefabs/Pedestal.prefab index 56ae659c6b..c2e4a1e79f 100644 --- a/Assets/Resources/EnvironmentPrefabs/Pedestal.prefab +++ b/Assets/Resources/EnvironmentPrefabs/Pedestal.prefab @@ -11,7 +11,7 @@ GameObject: - component: {fileID: 424176} - component: {fileID: 3352532} - component: {fileID: 2382690} - m_Layer: 0 + m_Layer: 25 m_Name: Geo_FloorBackground m_TagString: Untagged m_Icon: {fileID: 0} @@ -28,6 +28,7 @@ Transform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: -0, y: -0.5, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 463696} m_RootOrder: 0 @@ -51,9 +52,12 @@ MeshRenderer: m_CastShadows: 0 m_ReceiveShadows: 0 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -65,6 +69,7 @@ MeshRenderer: m_ProbeAnchor: {fileID: 0} m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 + m_ReceiveGI: 1 m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 @@ -77,6 +82,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!1 &113000 GameObject: m_ObjectHideFlags: 0 @@ -88,7 +94,7 @@ GameObject: - component: {fileID: 457156} - component: {fileID: 3355718} - component: {fileID: 2399512} - m_Layer: 0 + m_Layer: 25 m_Name: Geo_Spikes m_TagString: Untagged m_Icon: {fileID: 0} @@ -105,6 +111,7 @@ Transform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 0.4, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 463696} m_RootOrder: 2 @@ -128,9 +135,12 @@ MeshRenderer: m_CastShadows: 0 m_ReceiveShadows: 0 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -142,6 +152,7 @@ MeshRenderer: m_ProbeAnchor: {fileID: 0} m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 + m_ReceiveGI: 1 m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 @@ -154,6 +165,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!1 &114334 GameObject: m_ObjectHideFlags: 0 @@ -166,7 +178,7 @@ GameObject: - component: {fileID: 19893150} - component: {fileID: 19979650} - component: {fileID: 114157723204081412} - m_Layer: 0 + m_Layer: 25 m_Name: DustMotes m_TagString: Untagged m_Icon: {fileID: 0} @@ -183,6 +195,7 @@ Transform: m_LocalRotation: {x: -0.7071068, y: 0, z: 0, w: 0.7071068} m_LocalPosition: {x: 0, y: 15, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 463696} m_RootOrder: 4 @@ -194,19 +207,19 @@ ParticleSystem: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 114334} - serializedVersion: 6 + serializedVersion: 8 lengthInSec: 5 simulationSpeed: 1 stopAction: 0 cullingMode: 1 ringBufferMode: 0 ringBufferLoopRange: {x: 0, y: 1} + emitterVelocityMode: 0 looping: 1 prewarm: 1 playOnAwake: 1 useUnscaledTime: 0 autoRandomSeed: 1 - useRigidbodyForVelocity: 1 startDelay: serializedVersion: 2 minMaxState: 0 @@ -756,6 +769,7 @@ ParticleSystem: m_RotationOrder: 4 randomizeRotationDirection: 0 maxNumParticles: 1000 + customEmitterVelocity: {x: 0, y: 0, z: 0} size3D: 0 rotation3D: 0 gravityModifier: @@ -1533,6 +1547,7 @@ ParticleSystem: m_NumColorKeys: 2 m_NumAlphaKeys: 2 UVModule: + serializedVersion: 2 enabled: 0 mode: 0 timeMode: 0 @@ -1632,7 +1647,7 @@ ParticleSystem: rowIndex: 0 cycles: 1 uvChannelMask: -1 - randomRow: 1 + rowMode: 1 sprites: - sprite: {fileID: 0} flipU: 0 @@ -2279,6 +2294,62 @@ ParticleSystem: m_PreInfinity: 2 m_PostInfinity: 2 m_RotationOrder: 4 + LifetimeByEmitterSpeedModule: + enabled: 0 + m_Curve: + serializedVersion: 2 + minMaxState: 1 + scalar: 1 + minScalar: 1 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: -0.8 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 0.2 + inSlope: -0.8 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + m_Range: {x: 0, y: 1} ForceModule: enabled: 0 x: @@ -2443,8 +2514,61 @@ ParticleSystem: inWorldSpace: 0 randomizePerFrame: 0 ExternalForcesModule: + serializedVersion: 2 enabled: 0 - multiplier: 1 + multiplierCurve: + serializedVersion: 2 + minMaxState: 0 + scalar: 1 + minScalar: 1 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 influenceFilter: 0 influenceMask: serializedVersion: 2 @@ -3656,19 +3780,20 @@ ParticleSystem: range: {x: 0, y: 1} CollisionModule: enabled: 0 - serializedVersion: 3 + serializedVersion: 4 type: 0 collisionMode: 0 colliderForce: 0 multiplyColliderForceByParticleSize: 0 multiplyColliderForceByParticleSpeed: 0 multiplyColliderForceByCollisionAngle: 1 - plane0: {fileID: 0} - plane1: {fileID: 0} - plane2: {fileID: 0} - plane3: {fileID: 0} - plane4: {fileID: 0} - plane5: {fileID: 0} + m_Planes: + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} m_Dampen: serializedVersion: 2 minMaxState: 0 @@ -3842,17 +3967,20 @@ ParticleSystem: interiorCollisions: 1 TriggerModule: enabled: 0 - collisionShape0: {fileID: 0} - collisionShape1: {fileID: 0} - collisionShape2: {fileID: 0} - collisionShape3: {fileID: 0} - collisionShape4: {fileID: 0} - collisionShape5: {fileID: 0} + serializedVersion: 2 inside: 1 outside: 0 enter: 0 exit: 0 + colliderQueryMode: 0 radiusScale: 1 + primitives: + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} SubModule: serializedVersion: 2 enabled: 0 @@ -4803,9 +4931,12 @@ ParticleSystemRenderer: m_CastShadows: 1 m_ReceiveShadows: 1 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 + m_RayTracingMode: 0 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -4818,6 +4949,7 @@ ParticleSystemRenderer: m_ProbeAnchor: {fileID: 0} m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 + m_ReceiveGI: 1 m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 @@ -4831,6 +4963,7 @@ ParticleSystemRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_RenderMode: 0 + m_MeshDistribution: 0 m_SortMode: 0 m_MinParticleSize: 0 m_MaxParticleSize: 0.5 @@ -4847,11 +4980,17 @@ ParticleSystemRenderer: m_EnableGPUInstancing: 0 m_ApplyActiveColorSpace: 0 m_AllowRoll: 1 + m_FreeformStretching: 0 + m_RotateWithStretchDirection: 1 m_VertexStreams: 0001030405 m_Mesh: {fileID: 0} m_Mesh1: {fileID: 0} m_Mesh2: {fileID: 0} m_Mesh3: {fileID: 0} + m_MeshWeighting: 1 + m_MeshWeighting1: 1 + m_MeshWeighting2: 1 + m_MeshWeighting3: 1 m_MaskInteraction: 0 --- !u!114 &114157723204081412 MonoBehaviour: @@ -4880,7 +5019,7 @@ GameObject: - component: {fileID: 3392160} - component: {fileID: 2316744} - component: {fileID: 114969557637603980} - m_Layer: 0 + m_Layer: 25 m_Name: GroundDisk m_TagString: Untagged m_Icon: {fileID: 0} @@ -4897,6 +5036,7 @@ Transform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: -0.5, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 463696} m_RootOrder: 6 @@ -4920,9 +5060,12 @@ MeshRenderer: m_CastShadows: 0 m_ReceiveShadows: 0 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -4934,6 +5077,7 @@ MeshRenderer: m_ProbeAnchor: {fileID: 0} m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 + m_ReceiveGI: 1 m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 @@ -4946,6 +5090,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!114 &114969557637603980 MonoBehaviour: m_ObjectHideFlags: 0 @@ -4972,7 +5117,7 @@ GameObject: - component: {fileID: 486512} - component: {fileID: 3388836} - component: {fileID: 2301376} - m_Layer: 0 + m_Layer: 25 m_Name: Pedestal m_TagString: Untagged m_Icon: {fileID: 0} @@ -4989,6 +5134,7 @@ Transform: m_LocalRotation: {x: -0.70751375, y: 0, z: 0, w: 0.7066996} m_LocalPosition: {x: 0, y: 0.21699998, z: 5} m_LocalScale: {x: 23.360954, y: 23.360958, z: 18.2} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 463696} m_RootOrder: 3 @@ -5012,9 +5158,12 @@ MeshRenderer: m_CastShadows: 1 m_ReceiveShadows: 1 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -5026,6 +5175,7 @@ MeshRenderer: m_ProbeAnchor: {fileID: 0} m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 + m_ReceiveGI: 1 m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 @@ -5038,6 +5188,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!1 &178168 GameObject: m_ObjectHideFlags: 0 @@ -5049,7 +5200,7 @@ GameObject: - component: {fileID: 460940} - component: {fileID: 3396076} - component: {fileID: 2319138} - m_Layer: 0 + m_Layer: 25 m_Name: Geo_FloorForeground m_TagString: Untagged m_Icon: {fileID: 0} @@ -5066,6 +5217,7 @@ Transform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: -0, y: -0.25, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 463696} m_RootOrder: 1 @@ -5089,9 +5241,12 @@ MeshRenderer: m_CastShadows: 0 m_ReceiveShadows: 1 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -5103,6 +5258,7 @@ MeshRenderer: m_ProbeAnchor: {fileID: 0} m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 + m_ReceiveGI: 1 m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 @@ -5115,6 +5271,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!1 &191288 GameObject: m_ObjectHideFlags: 0 @@ -5126,7 +5283,7 @@ GameObject: - component: {fileID: 456760} - component: {fileID: 3337052} - component: {fileID: 2351882} - m_Layer: 0 + m_Layer: 25 m_Name: Geo_PropStage m_TagString: Untagged m_Icon: {fileID: 0} @@ -5143,6 +5300,7 @@ Transform: m_LocalRotation: {x: 0, y: 1, z: 0, w: 0} m_LocalPosition: {x: 0, y: -0.25, z: 0} m_LocalScale: {x: 3, y: 0.05, z: 3} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 463696} m_RootOrder: 5 @@ -5166,9 +5324,12 @@ MeshRenderer: m_CastShadows: 1 m_ReceiveShadows: 1 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -5180,6 +5341,7 @@ MeshRenderer: m_ProbeAnchor: {fileID: 0} m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 + m_ReceiveGI: 1 m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 @@ -5192,6 +5354,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!1 &193958 GameObject: m_ObjectHideFlags: 0 @@ -5203,7 +5366,7 @@ GameObject: - component: {fileID: 492302} - component: {fileID: 3314278} - component: {fileID: 2342112} - m_Layer: 0 + m_Layer: 25 m_Name: GroundUnderside m_TagString: Untagged m_Icon: {fileID: 0} @@ -5220,6 +5383,7 @@ Transform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: -0.5, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 463696} m_RootOrder: 7 @@ -5243,9 +5407,12 @@ MeshRenderer: m_CastShadows: 1 m_ReceiveShadows: 1 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -5257,6 +5424,7 @@ MeshRenderer: m_ProbeAnchor: {fileID: 0} m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 + m_ReceiveGI: 1 m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 @@ -5269,6 +5437,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!1 &195766 GameObject: m_ObjectHideFlags: 0 @@ -5278,7 +5447,7 @@ GameObject: serializedVersion: 6 m_Component: - component: {fileID: 463696} - m_Layer: 0 + m_Layer: 25 m_Name: Pedestal m_TagString: Untagged m_Icon: {fileID: 0} @@ -5295,6 +5464,7 @@ Transform: 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_ConstrainProportionsScale: 0 m_Children: - {fileID: 424176} - {fileID: 460940} diff --git a/Assets/Resources/EnvironmentPrefabs/Snowman.prefab b/Assets/Resources/EnvironmentPrefabs/Snowman.prefab index 5b35d1acaf..b12aba710f 100644 --- a/Assets/Resources/EnvironmentPrefabs/Snowman.prefab +++ b/Assets/Resources/EnvironmentPrefabs/Snowman.prefab @@ -11,7 +11,7 @@ GameObject: - component: {fileID: 445372} - component: {fileID: 3345122} - component: {fileID: 2380094} - m_Layer: 0 + m_Layer: 25 m_Name: HemiSphere m_TagString: Untagged m_Icon: {fileID: 0} @@ -28,6 +28,7 @@ Transform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: -129, z: 0} m_LocalScale: {x: 975.3, y: 1073.689, z: 975.29956} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 402394} m_RootOrder: 4 @@ -51,9 +52,12 @@ MeshRenderer: m_CastShadows: 0 m_ReceiveShadows: 0 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -65,6 +69,7 @@ MeshRenderer: m_ProbeAnchor: {fileID: 0} m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 + m_ReceiveGI: 1 m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 @@ -77,6 +82,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!1 &121900 GameObject: m_ObjectHideFlags: 0 @@ -86,7 +92,7 @@ GameObject: serializedVersion: 6 m_Component: - component: {fileID: 402394} - m_Layer: 0 + m_Layer: 25 m_Name: Snowman m_TagString: Untagged m_Icon: {fileID: 0} @@ -103,6 +109,7 @@ Transform: 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_ConstrainProportionsScale: 0 m_Children: - {fileID: 485540} - {fileID: 445238} @@ -124,7 +131,7 @@ GameObject: - component: {fileID: 445238} - component: {fileID: 3317600} - component: {fileID: 2369508} - m_Layer: 0 + m_Layer: 25 m_Name: Geo_Snowman m_TagString: Untagged m_Icon: {fileID: 0} @@ -141,6 +148,7 @@ Transform: m_LocalRotation: {x: 0, y: 0.92387956, z: 0, w: 0.3826833} m_LocalPosition: {x: 0, y: 0, z: 5} m_LocalScale: {x: 0.069999985, y: 0.07, z: 0.06999999} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 402394} m_RootOrder: 1 @@ -164,9 +172,12 @@ MeshRenderer: m_CastShadows: 1 m_ReceiveShadows: 1 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -178,6 +189,7 @@ MeshRenderer: m_ProbeAnchor: {fileID: 0} m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 + m_ReceiveGI: 1 m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 @@ -190,6 +202,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!1 &157716 GameObject: m_ObjectHideFlags: 0 @@ -201,7 +214,7 @@ GameObject: - component: {fileID: 485540} - component: {fileID: 3337880} - component: {fileID: 2310628} - m_Layer: 0 + m_Layer: 25 m_Name: Geo_Ground m_TagString: Untagged m_Icon: {fileID: 0} @@ -218,6 +231,7 @@ Transform: m_LocalRotation: {x: 0, y: 0.92387956, z: 0, w: 0.3826833} m_LocalPosition: {x: 0.06391762, y: 94.89275, z: 5.016025} m_LocalScale: {x: 0.069999985, y: 0.07, z: 0.06999999} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 402394} m_RootOrder: 0 @@ -241,9 +255,12 @@ MeshRenderer: m_CastShadows: 1 m_ReceiveShadows: 1 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -255,6 +272,7 @@ MeshRenderer: m_ProbeAnchor: {fileID: 0} m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 + m_ReceiveGI: 1 m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 @@ -267,6 +285,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!1 &172598 GameObject: m_ObjectHideFlags: 0 @@ -278,7 +297,7 @@ GameObject: - component: {fileID: 458956} - component: {fileID: 19847152} - component: {fileID: 19985736} - m_Layer: 0 + m_Layer: 25 m_Name: Snow m_TagString: Untagged m_Icon: {fileID: 0} @@ -295,6 +314,7 @@ Transform: m_LocalRotation: {x: 0, y: 0.92387956, z: 0, w: 0.3826833} m_LocalPosition: {x: 0.030935913, y: 49.21, z: 4.969064} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 402394} m_RootOrder: 2 @@ -306,19 +326,19 @@ ParticleSystem: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 172598} - serializedVersion: 6 + serializedVersion: 8 lengthInSec: 5 simulationSpeed: 1 stopAction: 0 cullingMode: 3 ringBufferMode: 0 ringBufferLoopRange: {x: 0, y: 1} + emitterVelocityMode: 0 looping: 1 prewarm: 1 playOnAwake: 1 useUnscaledTime: 0 autoRandomSeed: 1 - useRigidbodyForVelocity: 1 startDelay: serializedVersion: 2 minMaxState: 0 @@ -814,6 +834,7 @@ ParticleSystem: m_RotationOrder: 4 randomizeRotationDirection: 0 maxNumParticles: 10000 + customEmitterVelocity: {x: 0, y: 0, z: 0} size3D: 0 rotation3D: 0 gravityModifier: @@ -1573,6 +1594,7 @@ ParticleSystem: m_NumColorKeys: 2 m_NumAlphaKeys: 2 UVModule: + serializedVersion: 2 enabled: 0 mode: 0 timeMode: 0 @@ -1672,7 +1694,7 @@ ParticleSystem: rowIndex: 0 cycles: 1 uvChannelMask: -1 - randomRow: 0 + rowMode: 0 sprites: - sprite: {fileID: 0} flipU: 0 @@ -2319,6 +2341,62 @@ ParticleSystem: m_PreInfinity: 2 m_PostInfinity: 2 m_RotationOrder: 4 + LifetimeByEmitterSpeedModule: + enabled: 0 + m_Curve: + serializedVersion: 2 + minMaxState: 1 + scalar: 1 + minScalar: 1 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: -0.8 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 0.2 + inSlope: -0.8 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + m_Range: {x: 0, y: 1} ForceModule: enabled: 1 x: @@ -2528,8 +2606,61 @@ ParticleSystem: inWorldSpace: 0 randomizePerFrame: 0 ExternalForcesModule: + serializedVersion: 2 enabled: 0 - multiplier: 1 + multiplierCurve: + serializedVersion: 2 + minMaxState: 0 + scalar: 1 + minScalar: 1 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 influenceFilter: 0 influenceMask: serializedVersion: 2 @@ -3741,19 +3872,20 @@ ParticleSystem: range: {x: 0, y: 1} CollisionModule: enabled: 0 - serializedVersion: 3 + serializedVersion: 4 type: 0 collisionMode: 0 colliderForce: 0 multiplyColliderForceByParticleSize: 0 multiplyColliderForceByParticleSpeed: 0 multiplyColliderForceByCollisionAngle: 1 - plane0: {fileID: 0} - plane1: {fileID: 0} - plane2: {fileID: 0} - plane3: {fileID: 0} - plane4: {fileID: 0} - plane5: {fileID: 0} + m_Planes: + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} m_Dampen: serializedVersion: 2 minMaxState: 0 @@ -3927,17 +4059,20 @@ ParticleSystem: interiorCollisions: 1 TriggerModule: enabled: 0 - collisionShape0: {fileID: 0} - collisionShape1: {fileID: 0} - collisionShape2: {fileID: 0} - collisionShape3: {fileID: 0} - collisionShape4: {fileID: 0} - collisionShape5: {fileID: 0} + serializedVersion: 2 inside: 1 outside: 0 enter: 0 exit: 0 + colliderQueryMode: 0 radiusScale: 1 + primitives: + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} SubModule: serializedVersion: 2 enabled: 0 @@ -4888,9 +5023,12 @@ ParticleSystemRenderer: m_CastShadows: 0 m_ReceiveShadows: 0 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 0 m_ReflectionProbeUsage: 0 + m_RayTracingMode: 0 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -4903,6 +5041,7 @@ ParticleSystemRenderer: m_ProbeAnchor: {fileID: 0} m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 + m_ReceiveGI: 1 m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 @@ -4916,6 +5055,7 @@ ParticleSystemRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_RenderMode: 0 + m_MeshDistribution: 0 m_SortMode: 0 m_MinParticleSize: 0 m_MaxParticleSize: 0.2 @@ -4932,11 +5072,17 @@ ParticleSystemRenderer: m_EnableGPUInstancing: 0 m_ApplyActiveColorSpace: 0 m_AllowRoll: 1 + m_FreeformStretching: 0 + m_RotateWithStretchDirection: 1 m_VertexStreams: 0001030405 m_Mesh: {fileID: 0} m_Mesh1: {fileID: 0} m_Mesh2: {fileID: 0} m_Mesh3: {fileID: 0} + m_MeshWeighting: 1 + m_MeshWeighting1: 1 + m_MeshWeighting2: 1 + m_MeshWeighting3: 1 m_MaskInteraction: 0 --- !u!1 &186758 GameObject: @@ -4949,7 +5095,7 @@ GameObject: - component: {fileID: 447626} - component: {fileID: 19807346} - component: {fileID: 19973004} - m_Layer: 0 + m_Layer: 25 m_Name: SnowFiller m_TagString: Untagged m_Icon: {fileID: 0} @@ -4966,6 +5112,7 @@ Transform: m_LocalRotation: {x: 0, y: 0.92387956, z: 0, w: 0.3826833} m_LocalPosition: {x: 0.030935831, y: 49.21, z: 4.969064} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 402394} m_RootOrder: 3 @@ -4977,19 +5124,19 @@ ParticleSystem: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 186758} - serializedVersion: 6 + serializedVersion: 8 lengthInSec: 5 simulationSpeed: 1 stopAction: 0 cullingMode: 3 ringBufferMode: 0 ringBufferLoopRange: {x: 0, y: 1} + emitterVelocityMode: 0 looping: 1 prewarm: 0 playOnAwake: 1 useUnscaledTime: 0 autoRandomSeed: 1 - useRigidbodyForVelocity: 1 startDelay: serializedVersion: 2 minMaxState: 0 @@ -5485,6 +5632,7 @@ ParticleSystem: m_RotationOrder: 4 randomizeRotationDirection: 0 maxNumParticles: 10000 + customEmitterVelocity: {x: 0, y: 0, z: 0} size3D: 0 rotation3D: 0 gravityModifier: @@ -6244,6 +6392,7 @@ ParticleSystem: m_NumColorKeys: 2 m_NumAlphaKeys: 2 UVModule: + serializedVersion: 2 enabled: 0 mode: 0 timeMode: 0 @@ -6343,7 +6492,7 @@ ParticleSystem: rowIndex: 0 cycles: 1 uvChannelMask: -1 - randomRow: 0 + rowMode: 0 sprites: - sprite: {fileID: 0} flipU: 0 @@ -6990,6 +7139,62 @@ ParticleSystem: m_PreInfinity: 2 m_PostInfinity: 2 m_RotationOrder: 4 + LifetimeByEmitterSpeedModule: + enabled: 0 + m_Curve: + serializedVersion: 2 + minMaxState: 1 + scalar: 1 + minScalar: 1 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: -0.8 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 0.2 + inSlope: -0.8 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + m_Range: {x: 0, y: 1} ForceModule: enabled: 1 x: @@ -7199,8 +7404,61 @@ ParticleSystem: inWorldSpace: 0 randomizePerFrame: 0 ExternalForcesModule: + serializedVersion: 2 enabled: 0 - multiplier: 1 + multiplierCurve: + serializedVersion: 2 + minMaxState: 0 + scalar: 1 + minScalar: 1 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 influenceFilter: 0 influenceMask: serializedVersion: 2 @@ -8412,19 +8670,20 @@ ParticleSystem: range: {x: 0, y: 1} CollisionModule: enabled: 0 - serializedVersion: 3 + serializedVersion: 4 type: 0 collisionMode: 0 colliderForce: 0 multiplyColliderForceByParticleSize: 0 multiplyColliderForceByParticleSpeed: 0 multiplyColliderForceByCollisionAngle: 1 - plane0: {fileID: 0} - plane1: {fileID: 0} - plane2: {fileID: 0} - plane3: {fileID: 0} - plane4: {fileID: 0} - plane5: {fileID: 0} + m_Planes: + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} m_Dampen: serializedVersion: 2 minMaxState: 0 @@ -8598,17 +8857,20 @@ ParticleSystem: interiorCollisions: 1 TriggerModule: enabled: 0 - collisionShape0: {fileID: 0} - collisionShape1: {fileID: 0} - collisionShape2: {fileID: 0} - collisionShape3: {fileID: 0} - collisionShape4: {fileID: 0} - collisionShape5: {fileID: 0} + serializedVersion: 2 inside: 1 outside: 0 enter: 0 exit: 0 + colliderQueryMode: 0 radiusScale: 1 + primitives: + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} SubModule: serializedVersion: 2 enabled: 0 @@ -9559,9 +9821,12 @@ ParticleSystemRenderer: m_CastShadows: 0 m_ReceiveShadows: 0 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 0 m_ReflectionProbeUsage: 0 + m_RayTracingMode: 0 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -9574,6 +9839,7 @@ ParticleSystemRenderer: m_ProbeAnchor: {fileID: 0} m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 + m_ReceiveGI: 1 m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 @@ -9587,6 +9853,7 @@ ParticleSystemRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_RenderMode: 0 + m_MeshDistribution: 0 m_SortMode: 0 m_MinParticleSize: 0 m_MaxParticleSize: 0.2 @@ -9603,11 +9870,17 @@ ParticleSystemRenderer: m_EnableGPUInstancing: 0 m_ApplyActiveColorSpace: 0 m_AllowRoll: 1 + m_FreeformStretching: 0 + m_RotateWithStretchDirection: 1 m_VertexStreams: 0001030405 m_Mesh: {fileID: 0} m_Mesh1: {fileID: 0} m_Mesh2: {fileID: 0} m_Mesh3: {fileID: 0} + m_MeshWeighting: 1 + m_MeshWeighting1: 1 + m_MeshWeighting2: 1 + m_MeshWeighting3: 1 m_MaskInteraction: 0 --- !u!1 &197206 GameObject: @@ -9620,7 +9893,7 @@ GameObject: - component: {fileID: 445918} - component: {fileID: 3309060} - component: {fileID: 2384180} - m_Layer: 0 + m_Layer: 25 m_Name: Geo_GroundBackfaces m_TagString: Untagged m_Icon: {fileID: 0} @@ -9637,6 +9910,7 @@ Transform: m_LocalRotation: {x: 0, y: 0.92387956, z: 0, w: 0.3826833} m_LocalPosition: {x: 0.06391762, y: 94.89275, z: 5.016025} m_LocalScale: {x: 0.06999998, y: 0.07, z: 0.06999999} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 402394} m_RootOrder: 5 @@ -9660,9 +9934,12 @@ MeshRenderer: m_CastShadows: 0 m_ReceiveShadows: 0 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 0 m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -9674,6 +9951,7 @@ MeshRenderer: m_ProbeAnchor: {fileID: 0} m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 + m_ReceiveGI: 1 m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 @@ -9686,3 +9964,4 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} diff --git a/Assets/Resources/EnvironmentPrefabs/Space.prefab b/Assets/Resources/EnvironmentPrefabs/Space.prefab index eac8183d69..c24d4a0ccc 100644 --- a/Assets/Resources/EnvironmentPrefabs/Space.prefab +++ b/Assets/Resources/EnvironmentPrefabs/Space.prefab @@ -11,7 +11,7 @@ GameObject: - component: {fileID: 434888} - component: {fileID: 3368352} - component: {fileID: 2327474} - m_Layer: 0 + m_Layer: 25 m_Name: Moon m_TagString: Untagged m_Icon: {fileID: 0} @@ -28,6 +28,7 @@ Transform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 13, z: 5} m_LocalScale: {x: 3.6417453, y: 3.6417463, z: 3.6417463} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 444254} m_RootOrder: 0 @@ -51,9 +52,12 @@ MeshRenderer: m_CastShadows: 1 m_ReceiveShadows: 1 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -65,6 +69,7 @@ MeshRenderer: m_ProbeAnchor: {fileID: 0} m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 + m_ReceiveGI: 1 m_PreserveUVs: 1 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 @@ -77,6 +82,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!1 &132296 GameObject: m_ObjectHideFlags: 0 @@ -86,7 +92,7 @@ GameObject: serializedVersion: 6 m_Component: - component: {fileID: 444254} - m_Layer: 0 + m_Layer: 25 m_Name: Space m_TagString: Untagged m_Icon: {fileID: 0} @@ -103,6 +109,7 @@ Transform: 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_ConstrainProportionsScale: 0 m_Children: - {fileID: 434888} - {fileID: 405328} @@ -126,7 +133,7 @@ GameObject: - component: {fileID: 475926} - component: {fileID: 19837794} - component: {fileID: 19975236} - m_Layer: 0 + m_Layer: 25 m_Name: StarParticles3 m_TagString: Untagged m_Icon: {fileID: 0} @@ -143,6 +150,7 @@ Transform: m_LocalRotation: {x: -0.7071068, y: 0, z: 0, w: 0.7071068} m_LocalPosition: {x: 0, y: 15, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 444254} m_RootOrder: 3 @@ -154,19 +162,19 @@ ParticleSystem: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 136844} - serializedVersion: 6 + serializedVersion: 8 lengthInSec: 5 simulationSpeed: 1 stopAction: 0 cullingMode: 1 ringBufferMode: 0 ringBufferLoopRange: {x: 0, y: 1} + emitterVelocityMode: 0 looping: 1 prewarm: 1 playOnAwake: 1 useUnscaledTime: 0 autoRandomSeed: 1 - useRigidbodyForVelocity: 1 startDelay: serializedVersion: 2 minMaxState: 0 @@ -716,6 +724,7 @@ ParticleSystem: m_RotationOrder: 4 randomizeRotationDirection: 0 maxNumParticles: 1000 + customEmitterVelocity: {x: 0, y: 0, z: 0} size3D: 0 rotation3D: 0 gravityModifier: @@ -1493,6 +1502,7 @@ ParticleSystem: m_NumColorKeys: 2 m_NumAlphaKeys: 2 UVModule: + serializedVersion: 2 enabled: 1 mode: 0 timeMode: 0 @@ -1592,7 +1602,7 @@ ParticleSystem: rowIndex: 0 cycles: 1 uvChannelMask: -1 - randomRow: 1 + rowMode: 1 sprites: - sprite: {fileID: 0} flipU: 0 @@ -2239,6 +2249,62 @@ ParticleSystem: m_PreInfinity: 2 m_PostInfinity: 2 m_RotationOrder: 4 + LifetimeByEmitterSpeedModule: + enabled: 0 + m_Curve: + serializedVersion: 2 + minMaxState: 1 + scalar: 1 + minScalar: 1 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: -0.8 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 0.2 + inSlope: -0.8 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + m_Range: {x: 0, y: 1} ForceModule: enabled: 0 x: @@ -2403,8 +2469,61 @@ ParticleSystem: inWorldSpace: 0 randomizePerFrame: 0 ExternalForcesModule: + serializedVersion: 2 enabled: 0 - multiplier: 1 + multiplierCurve: + serializedVersion: 2 + minMaxState: 0 + scalar: 1 + minScalar: 1 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 influenceFilter: 0 influenceMask: serializedVersion: 2 @@ -3616,19 +3735,20 @@ ParticleSystem: range: {x: 0, y: 1} CollisionModule: enabled: 0 - serializedVersion: 3 + serializedVersion: 4 type: 0 collisionMode: 0 colliderForce: 0 multiplyColliderForceByParticleSize: 0 multiplyColliderForceByParticleSpeed: 0 multiplyColliderForceByCollisionAngle: 1 - plane0: {fileID: 0} - plane1: {fileID: 0} - plane2: {fileID: 0} - plane3: {fileID: 0} - plane4: {fileID: 0} - plane5: {fileID: 0} + m_Planes: + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} m_Dampen: serializedVersion: 2 minMaxState: 0 @@ -3802,17 +3922,20 @@ ParticleSystem: interiorCollisions: 1 TriggerModule: enabled: 0 - collisionShape0: {fileID: 0} - collisionShape1: {fileID: 0} - collisionShape2: {fileID: 0} - collisionShape3: {fileID: 0} - collisionShape4: {fileID: 0} - collisionShape5: {fileID: 0} + serializedVersion: 2 inside: 1 outside: 0 enter: 0 exit: 0 + colliderQueryMode: 0 radiusScale: 1 + primitives: + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} SubModule: serializedVersion: 2 enabled: 0 @@ -4763,9 +4886,12 @@ ParticleSystemRenderer: m_CastShadows: 1 m_ReceiveShadows: 1 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 + m_RayTracingMode: 0 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -4778,6 +4904,7 @@ ParticleSystemRenderer: m_ProbeAnchor: {fileID: 0} m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 + m_ReceiveGI: 1 m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 @@ -4791,6 +4918,7 @@ ParticleSystemRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_RenderMode: 0 + m_MeshDistribution: 0 m_SortMode: 0 m_MinParticleSize: 0 m_MaxParticleSize: 0.5 @@ -4807,11 +4935,17 @@ ParticleSystemRenderer: m_EnableGPUInstancing: 0 m_ApplyActiveColorSpace: 0 m_AllowRoll: 1 + m_FreeformStretching: 0 + m_RotateWithStretchDirection: 1 m_VertexStreams: 0001030405 m_Mesh: {fileID: 0} m_Mesh1: {fileID: 0} m_Mesh2: {fileID: 0} m_Mesh3: {fileID: 0} + m_MeshWeighting: 1 + m_MeshWeighting1: 1 + m_MeshWeighting2: 1 + m_MeshWeighting3: 1 m_MaskInteraction: 0 --- !u!1 &139100 GameObject: @@ -4825,7 +4959,7 @@ GameObject: - component: {fileID: 3362916} - component: {fileID: 6499546} - component: {fileID: 2367046} - m_Layer: 0 + m_Layer: 25 m_Name: Flare (2) m_TagString: Untagged m_Icon: {fileID: 0} @@ -4842,6 +4976,7 @@ Transform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 2.8080032, y: -0.007659245, z: -21.834728} m_LocalScale: {x: 0.2, y: 0.2, z: 0.2} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 466976} m_RootOrder: 2 @@ -4864,9 +4999,9 @@ MeshCollider: m_Material: {fileID: 0} m_IsTrigger: 0 m_Enabled: 1 - serializedVersion: 3 + serializedVersion: 4 m_Convex: 0 - m_CookingOptions: 14 + m_CookingOptions: 30 m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} --- !u!23 &2367046 MeshRenderer: @@ -4879,9 +5014,12 @@ MeshRenderer: m_CastShadows: 1 m_ReceiveShadows: 1 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -4893,6 +5031,7 @@ MeshRenderer: m_ProbeAnchor: {fileID: 0} m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 + m_ReceiveGI: 1 m_PreserveUVs: 1 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 @@ -4905,6 +5044,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!1 &156152 GameObject: m_ObjectHideFlags: 0 @@ -4917,7 +5057,7 @@ GameObject: - component: {fileID: 3394466} - component: {fileID: 6414138} - component: {fileID: 2320484} - m_Layer: 0 + m_Layer: 25 m_Name: Flare m_TagString: Untagged m_Icon: {fileID: 0} @@ -4934,6 +5074,7 @@ Transform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0.63420355, y: -0.058673907, z: -4.690826} m_LocalScale: {x: 8, y: 8, z: 8} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 466976} m_RootOrder: 0 @@ -4956,9 +5097,9 @@ MeshCollider: m_Material: {fileID: 0} m_IsTrigger: 0 m_Enabled: 1 - serializedVersion: 3 + serializedVersion: 4 m_Convex: 0 - m_CookingOptions: 14 + m_CookingOptions: 30 m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} --- !u!23 &2320484 MeshRenderer: @@ -4971,9 +5112,12 @@ MeshRenderer: m_CastShadows: 1 m_ReceiveShadows: 1 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -4985,6 +5129,7 @@ MeshRenderer: m_ProbeAnchor: {fileID: 0} m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 + m_ReceiveGI: 1 m_PreserveUVs: 1 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 @@ -4997,6 +5142,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!1 &163134 GameObject: m_ObjectHideFlags: 0 @@ -5008,7 +5154,7 @@ GameObject: - component: {fileID: 445294} - component: {fileID: 19805002} - component: {fileID: 19935524} - m_Layer: 0 + m_Layer: 25 m_Name: StarParticles2 m_TagString: Untagged m_Icon: {fileID: 0} @@ -5025,6 +5171,7 @@ Transform: m_LocalRotation: {x: -0.7071068, y: 0, z: 0, w: 0.7071068} m_LocalPosition: {x: 0, y: 15, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 444254} m_RootOrder: 2 @@ -5036,19 +5183,19 @@ ParticleSystem: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 163134} - serializedVersion: 6 + serializedVersion: 8 lengthInSec: 5 simulationSpeed: 1 stopAction: 0 cullingMode: 1 ringBufferMode: 0 ringBufferLoopRange: {x: 0, y: 1} + emitterVelocityMode: 0 looping: 1 prewarm: 1 playOnAwake: 1 useUnscaledTime: 0 autoRandomSeed: 1 - useRigidbodyForVelocity: 1 startDelay: serializedVersion: 2 minMaxState: 0 @@ -5580,6 +5727,7 @@ ParticleSystem: m_RotationOrder: 4 randomizeRotationDirection: 0 maxNumParticles: 1000 + customEmitterVelocity: {x: 0, y: 0, z: 0} size3D: 0 rotation3D: 0 gravityModifier: @@ -6357,6 +6505,7 @@ ParticleSystem: m_NumColorKeys: 2 m_NumAlphaKeys: 2 UVModule: + serializedVersion: 2 enabled: 1 mode: 0 timeMode: 0 @@ -6456,7 +6605,7 @@ ParticleSystem: rowIndex: 0 cycles: 1 uvChannelMask: -1 - randomRow: 1 + rowMode: 1 sprites: - sprite: {fileID: 0} flipU: 0 @@ -7103,6 +7252,62 @@ ParticleSystem: m_PreInfinity: 2 m_PostInfinity: 2 m_RotationOrder: 4 + LifetimeByEmitterSpeedModule: + enabled: 0 + m_Curve: + serializedVersion: 2 + minMaxState: 1 + scalar: 1 + minScalar: 1 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: -0.8 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 0.2 + inSlope: -0.8 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + m_Range: {x: 0, y: 1} ForceModule: enabled: 0 x: @@ -7267,8 +7472,61 @@ ParticleSystem: inWorldSpace: 0 randomizePerFrame: 0 ExternalForcesModule: + serializedVersion: 2 enabled: 0 - multiplier: 1 + multiplierCurve: + serializedVersion: 2 + minMaxState: 0 + scalar: 1 + minScalar: 1 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 influenceFilter: 0 influenceMask: serializedVersion: 2 @@ -8480,19 +8738,20 @@ ParticleSystem: range: {x: 0, y: 1} CollisionModule: enabled: 0 - serializedVersion: 3 + serializedVersion: 4 type: 0 collisionMode: 0 colliderForce: 0 multiplyColliderForceByParticleSize: 0 multiplyColliderForceByParticleSpeed: 0 multiplyColliderForceByCollisionAngle: 1 - plane0: {fileID: 0} - plane1: {fileID: 0} - plane2: {fileID: 0} - plane3: {fileID: 0} - plane4: {fileID: 0} - plane5: {fileID: 0} + m_Planes: + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} m_Dampen: serializedVersion: 2 minMaxState: 0 @@ -8666,17 +8925,20 @@ ParticleSystem: interiorCollisions: 1 TriggerModule: enabled: 0 - collisionShape0: {fileID: 0} - collisionShape1: {fileID: 0} - collisionShape2: {fileID: 0} - collisionShape3: {fileID: 0} - collisionShape4: {fileID: 0} - collisionShape5: {fileID: 0} + serializedVersion: 2 inside: 1 outside: 0 enter: 0 exit: 0 + colliderQueryMode: 0 radiusScale: 1 + primitives: + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} SubModule: serializedVersion: 2 enabled: 0 @@ -9627,9 +9889,12 @@ ParticleSystemRenderer: m_CastShadows: 1 m_ReceiveShadows: 1 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 + m_RayTracingMode: 0 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -9642,6 +9907,7 @@ ParticleSystemRenderer: m_ProbeAnchor: {fileID: 0} m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 + m_ReceiveGI: 1 m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 @@ -9655,6 +9921,7 @@ ParticleSystemRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_RenderMode: 0 + m_MeshDistribution: 0 m_SortMode: 0 m_MinParticleSize: 0 m_MaxParticleSize: 0.5 @@ -9671,11 +9938,17 @@ ParticleSystemRenderer: m_EnableGPUInstancing: 0 m_ApplyActiveColorSpace: 0 m_AllowRoll: 1 + m_FreeformStretching: 0 + m_RotateWithStretchDirection: 1 m_VertexStreams: 0001030405 m_Mesh: {fileID: 0} m_Mesh1: {fileID: 0} m_Mesh2: {fileID: 0} m_Mesh3: {fileID: 0} + m_MeshWeighting: 1 + m_MeshWeighting1: 1 + m_MeshWeighting2: 1 + m_MeshWeighting3: 1 m_MaskInteraction: 0 --- !u!1 &163938 GameObject: @@ -9688,7 +9961,7 @@ GameObject: - component: {fileID: 430766} - component: {fileID: 19832202} - component: {fileID: 19926748} - m_Layer: 0 + m_Layer: 25 m_Name: StarParticles5 m_TagString: Untagged m_Icon: {fileID: 0} @@ -9705,6 +9978,7 @@ Transform: m_LocalRotation: {x: -0.7071068, y: 0, z: 0, w: 0.7071068} m_LocalPosition: {x: 0, y: 15, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 444254} m_RootOrder: 5 @@ -9716,19 +9990,19 @@ ParticleSystem: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 163938} - serializedVersion: 6 + serializedVersion: 8 lengthInSec: 5 simulationSpeed: 1 stopAction: 0 cullingMode: 1 ringBufferMode: 0 ringBufferLoopRange: {x: 0, y: 1} + emitterVelocityMode: 0 looping: 1 prewarm: 1 playOnAwake: 1 useUnscaledTime: 0 autoRandomSeed: 1 - useRigidbodyForVelocity: 1 startDelay: serializedVersion: 2 minMaxState: 0 @@ -10278,6 +10552,7 @@ ParticleSystem: m_RotationOrder: 4 randomizeRotationDirection: 0 maxNumParticles: 1000 + customEmitterVelocity: {x: 0, y: 0, z: 0} size3D: 0 rotation3D: 0 gravityModifier: @@ -11055,6 +11330,7 @@ ParticleSystem: m_NumColorKeys: 2 m_NumAlphaKeys: 2 UVModule: + serializedVersion: 2 enabled: 1 mode: 0 timeMode: 0 @@ -11154,7 +11430,7 @@ ParticleSystem: rowIndex: 0 cycles: 1 uvChannelMask: -1 - randomRow: 1 + rowMode: 1 sprites: - sprite: {fileID: 0} flipU: 0 @@ -11801,13 +12077,13 @@ ParticleSystem: m_PreInfinity: 2 m_PostInfinity: 2 m_RotationOrder: 4 - ForceModule: + LifetimeByEmitterSpeedModule: enabled: 0 - x: + m_Curve: serializedVersion: 2 - minMaxState: 0 - scalar: 0 - minScalar: 0 + minMaxState: 1 + scalar: 1 + minScalar: 1 maxCurve: serializedVersion: 2 m_Curve: @@ -11815,15 +12091,15 @@ ParticleSystem: time: 0 value: 1 inSlope: 0 - outSlope: 0 + outSlope: -0.8 tangentMode: 0 weightedMode: 0 inWeight: 0.33333334 outWeight: 0.33333334 - serializedVersion: 3 time: 1 - value: 1 - inSlope: 0 + value: 0.2 + inSlope: -0.8 outSlope: 0 tangentMode: 0 weightedMode: 0 @@ -11837,7 +12113,7 @@ ParticleSystem: m_Curve: - serializedVersion: 3 time: 0 - value: 0 + value: 1 inSlope: 0 outSlope: 0 tangentMode: 0 @@ -11846,7 +12122,7 @@ ParticleSystem: outWeight: 0.33333334 - serializedVersion: 3 time: 1 - value: 0 + value: 1 inSlope: 0 outSlope: 0 tangentMode: 0 @@ -11856,7 +12132,10 @@ ParticleSystem: m_PreInfinity: 2 m_PostInfinity: 2 m_RotationOrder: 4 - y: + m_Range: {x: 0, y: 1} + ForceModule: + enabled: 0 + x: serializedVersion: 2 minMaxState: 0 scalar: 0 @@ -11909,7 +12188,7 @@ ParticleSystem: m_PreInfinity: 2 m_PostInfinity: 2 m_RotationOrder: 4 - z: + y: serializedVersion: 2 minMaxState: 0 scalar: 0 @@ -11962,22 +12241,128 @@ ParticleSystem: m_PreInfinity: 2 m_PostInfinity: 2 m_RotationOrder: 4 - inWorldSpace: 0 - randomizePerFrame: 0 - ExternalForcesModule: - enabled: 0 - multiplier: 1 - influenceFilter: 0 - influenceMask: - serializedVersion: 2 - m_Bits: 4294967295 - influenceList: [] - ClampVelocityModule: - enabled: 0 - x: + z: serializedVersion: 2 minMaxState: 0 - scalar: 1 + scalar: 0 + minScalar: 0 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + inWorldSpace: 0 + randomizePerFrame: 0 + ExternalForcesModule: + serializedVersion: 2 + enabled: 0 + multiplierCurve: + serializedVersion: 2 + minMaxState: 0 + scalar: 1 + minScalar: 1 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + influenceFilter: 0 + influenceMask: + serializedVersion: 2 + m_Bits: 4294967295 + influenceList: [] + ClampVelocityModule: + enabled: 0 + x: + serializedVersion: 2 + minMaxState: 0 + scalar: 1 minScalar: 1 maxCurve: serializedVersion: 2 @@ -13178,19 +13563,20 @@ ParticleSystem: range: {x: 0, y: 1} CollisionModule: enabled: 0 - serializedVersion: 3 + serializedVersion: 4 type: 0 collisionMode: 0 colliderForce: 0 multiplyColliderForceByParticleSize: 0 multiplyColliderForceByParticleSpeed: 0 multiplyColliderForceByCollisionAngle: 1 - plane0: {fileID: 0} - plane1: {fileID: 0} - plane2: {fileID: 0} - plane3: {fileID: 0} - plane4: {fileID: 0} - plane5: {fileID: 0} + m_Planes: + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} m_Dampen: serializedVersion: 2 minMaxState: 0 @@ -13364,17 +13750,20 @@ ParticleSystem: interiorCollisions: 1 TriggerModule: enabled: 0 - collisionShape0: {fileID: 0} - collisionShape1: {fileID: 0} - collisionShape2: {fileID: 0} - collisionShape3: {fileID: 0} - collisionShape4: {fileID: 0} - collisionShape5: {fileID: 0} + serializedVersion: 2 inside: 1 outside: 0 enter: 0 exit: 0 + colliderQueryMode: 0 radiusScale: 1 + primitives: + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} SubModule: serializedVersion: 2 enabled: 0 @@ -14325,9 +14714,12 @@ ParticleSystemRenderer: m_CastShadows: 1 m_ReceiveShadows: 1 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 + m_RayTracingMode: 0 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -14340,6 +14732,7 @@ ParticleSystemRenderer: m_ProbeAnchor: {fileID: 0} m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 + m_ReceiveGI: 1 m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 @@ -14353,6 +14746,7 @@ ParticleSystemRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_RenderMode: 0 + m_MeshDistribution: 0 m_SortMode: 0 m_MinParticleSize: 0 m_MaxParticleSize: 0.5 @@ -14369,11 +14763,17 @@ ParticleSystemRenderer: m_EnableGPUInstancing: 0 m_ApplyActiveColorSpace: 0 m_AllowRoll: 1 + m_FreeformStretching: 0 + m_RotateWithStretchDirection: 1 m_VertexStreams: 0001030405 m_Mesh: {fileID: 0} m_Mesh1: {fileID: 0} m_Mesh2: {fileID: 0} m_Mesh3: {fileID: 0} + m_MeshWeighting: 1 + m_MeshWeighting1: 1 + m_MeshWeighting2: 1 + m_MeshWeighting3: 1 m_MaskInteraction: 0 --- !u!1 &181288 GameObject: @@ -14387,7 +14787,7 @@ GameObject: - component: {fileID: 3399614} - component: {fileID: 6427118} - component: {fileID: 2322542} - m_Layer: 0 + m_Layer: 25 m_Name: Flare (1) m_TagString: Untagged m_Icon: {fileID: 0} @@ -14404,6 +14804,7 @@ Transform: m_LocalRotation: {x: 0, y: 0, z: 0.07428203, w: -0.99723727} m_LocalPosition: {x: 2.4045722, y: 0.0139310835, z: -18.784296} m_LocalScale: {x: 0.2, y: 0.2, z: 0.2} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 466976} m_RootOrder: 1 @@ -14426,9 +14827,9 @@ MeshCollider: m_Material: {fileID: 0} m_IsTrigger: 0 m_Enabled: 1 - serializedVersion: 3 + serializedVersion: 4 m_Convex: 0 - m_CookingOptions: 14 + m_CookingOptions: 30 m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} --- !u!23 &2322542 MeshRenderer: @@ -14441,9 +14842,12 @@ MeshRenderer: m_CastShadows: 1 m_ReceiveShadows: 1 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -14455,6 +14859,7 @@ MeshRenderer: m_ProbeAnchor: {fileID: 0} m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 + m_ReceiveGI: 1 m_PreserveUVs: 1 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 @@ -14467,6 +14872,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!1 &182958 GameObject: m_ObjectHideFlags: 0 @@ -14478,7 +14884,7 @@ GameObject: - component: {fileID: 405328} - component: {fileID: 19823946} - component: {fileID: 19940492} - m_Layer: 0 + m_Layer: 25 m_Name: StarParticles1 m_TagString: Untagged m_Icon: {fileID: 0} @@ -14495,6 +14901,7 @@ Transform: m_LocalRotation: {x: -0.7071068, y: 0, z: 0, w: 0.7071068} m_LocalPosition: {x: 0, y: 15, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 444254} m_RootOrder: 1 @@ -14506,19 +14913,19 @@ ParticleSystem: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 182958} - serializedVersion: 6 + serializedVersion: 8 lengthInSec: 5 simulationSpeed: 1 stopAction: 0 cullingMode: 1 ringBufferMode: 0 ringBufferLoopRange: {x: 0, y: 1} + emitterVelocityMode: 0 looping: 1 prewarm: 1 playOnAwake: 1 useUnscaledTime: 0 autoRandomSeed: 1 - useRigidbodyForVelocity: 1 startDelay: serializedVersion: 2 minMaxState: 0 @@ -15050,6 +15457,7 @@ ParticleSystem: m_RotationOrder: 4 randomizeRotationDirection: 0 maxNumParticles: 1000 + customEmitterVelocity: {x: 0, y: 0, z: 0} size3D: 0 rotation3D: 0 gravityModifier: @@ -15827,6 +16235,7 @@ ParticleSystem: m_NumColorKeys: 2 m_NumAlphaKeys: 2 UVModule: + serializedVersion: 2 enabled: 1 mode: 0 timeMode: 0 @@ -15926,7 +16335,7 @@ ParticleSystem: rowIndex: 0 cycles: 1 uvChannelMask: -1 - randomRow: 1 + rowMode: 1 sprites: - sprite: {fileID: 0} flipU: 0 @@ -16573,6 +16982,62 @@ ParticleSystem: m_PreInfinity: 2 m_PostInfinity: 2 m_RotationOrder: 4 + LifetimeByEmitterSpeedModule: + enabled: 0 + m_Curve: + serializedVersion: 2 + minMaxState: 1 + scalar: 1 + minScalar: 1 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: -0.8 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 0.2 + inSlope: -0.8 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + m_Range: {x: 0, y: 1} ForceModule: enabled: 0 x: @@ -16737,8 +17202,61 @@ ParticleSystem: inWorldSpace: 0 randomizePerFrame: 0 ExternalForcesModule: + serializedVersion: 2 enabled: 0 - multiplier: 1 + multiplierCurve: + serializedVersion: 2 + minMaxState: 0 + scalar: 1 + minScalar: 1 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 influenceFilter: 0 influenceMask: serializedVersion: 2 @@ -17950,19 +18468,20 @@ ParticleSystem: range: {x: 0, y: 1} CollisionModule: enabled: 0 - serializedVersion: 3 + serializedVersion: 4 type: 0 collisionMode: 0 colliderForce: 0 multiplyColliderForceByParticleSize: 0 multiplyColliderForceByParticleSpeed: 0 multiplyColliderForceByCollisionAngle: 1 - plane0: {fileID: 0} - plane1: {fileID: 0} - plane2: {fileID: 0} - plane3: {fileID: 0} - plane4: {fileID: 0} - plane5: {fileID: 0} + m_Planes: + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} m_Dampen: serializedVersion: 2 minMaxState: 0 @@ -18136,17 +18655,20 @@ ParticleSystem: interiorCollisions: 1 TriggerModule: enabled: 0 - collisionShape0: {fileID: 0} - collisionShape1: {fileID: 0} - collisionShape2: {fileID: 0} - collisionShape3: {fileID: 0} - collisionShape4: {fileID: 0} - collisionShape5: {fileID: 0} + serializedVersion: 2 inside: 1 outside: 0 enter: 0 exit: 0 + colliderQueryMode: 0 radiusScale: 1 + primitives: + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} SubModule: serializedVersion: 2 enabled: 0 @@ -19097,9 +19619,12 @@ ParticleSystemRenderer: m_CastShadows: 1 m_ReceiveShadows: 1 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 + m_RayTracingMode: 0 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -19112,6 +19637,7 @@ ParticleSystemRenderer: m_ProbeAnchor: {fileID: 0} m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 + m_ReceiveGI: 1 m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 @@ -19125,6 +19651,7 @@ ParticleSystemRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_RenderMode: 0 + m_MeshDistribution: 0 m_SortMode: 0 m_MinParticleSize: 0 m_MaxParticleSize: 0.5 @@ -19141,11 +19668,17 @@ ParticleSystemRenderer: m_EnableGPUInstancing: 0 m_ApplyActiveColorSpace: 0 m_AllowRoll: 1 + m_FreeformStretching: 0 + m_RotateWithStretchDirection: 1 m_VertexStreams: 0001030405 m_Mesh: {fileID: 0} m_Mesh1: {fileID: 0} m_Mesh2: {fileID: 0} m_Mesh3: {fileID: 0} + m_MeshWeighting: 1 + m_MeshWeighting1: 1 + m_MeshWeighting2: 1 + m_MeshWeighting3: 1 m_MaskInteraction: 0 --- !u!1 &190718 GameObject: @@ -19158,7 +19691,7 @@ GameObject: - component: {fileID: 482038} - component: {fileID: 19829876} - component: {fileID: 19928512} - m_Layer: 0 + m_Layer: 25 m_Name: StarParticles4 m_TagString: Untagged m_Icon: {fileID: 0} @@ -19175,6 +19708,7 @@ Transform: m_LocalRotation: {x: -0.7071068, y: 0, z: 0, w: 0.7071068} m_LocalPosition: {x: 0, y: 15, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 444254} m_RootOrder: 4 @@ -19186,19 +19720,19 @@ ParticleSystem: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 190718} - serializedVersion: 6 + serializedVersion: 8 lengthInSec: 5 simulationSpeed: 1 stopAction: 0 cullingMode: 1 ringBufferMode: 0 ringBufferLoopRange: {x: 0, y: 1} + emitterVelocityMode: 0 looping: 1 prewarm: 1 playOnAwake: 1 useUnscaledTime: 0 autoRandomSeed: 1 - useRigidbodyForVelocity: 1 startDelay: serializedVersion: 2 minMaxState: 0 @@ -19748,6 +20282,7 @@ ParticleSystem: m_RotationOrder: 4 randomizeRotationDirection: 0 maxNumParticles: 1000 + customEmitterVelocity: {x: 0, y: 0, z: 0} size3D: 0 rotation3D: 0 gravityModifier: @@ -20525,6 +21060,7 @@ ParticleSystem: m_NumColorKeys: 2 m_NumAlphaKeys: 2 UVModule: + serializedVersion: 2 enabled: 1 mode: 0 timeMode: 0 @@ -20624,7 +21160,7 @@ ParticleSystem: rowIndex: 0 cycles: 1 uvChannelMask: -1 - randomRow: 1 + rowMode: 1 sprites: - sprite: {fileID: 0} flipU: 0 @@ -21271,6 +21807,62 @@ ParticleSystem: m_PreInfinity: 2 m_PostInfinity: 2 m_RotationOrder: 4 + LifetimeByEmitterSpeedModule: + enabled: 0 + m_Curve: + serializedVersion: 2 + minMaxState: 1 + scalar: 1 + minScalar: 1 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: -0.8 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 0.2 + inSlope: -0.8 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + m_Range: {x: 0, y: 1} ForceModule: enabled: 0 x: @@ -21435,8 +22027,61 @@ ParticleSystem: inWorldSpace: 0 randomizePerFrame: 0 ExternalForcesModule: + serializedVersion: 2 enabled: 0 - multiplier: 1 + multiplierCurve: + serializedVersion: 2 + minMaxState: 0 + scalar: 1 + minScalar: 1 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 influenceFilter: 0 influenceMask: serializedVersion: 2 @@ -22648,19 +23293,20 @@ ParticleSystem: range: {x: 0, y: 1} CollisionModule: enabled: 0 - serializedVersion: 3 + serializedVersion: 4 type: 0 collisionMode: 0 colliderForce: 0 multiplyColliderForceByParticleSize: 0 multiplyColliderForceByParticleSpeed: 0 multiplyColliderForceByCollisionAngle: 1 - plane0: {fileID: 0} - plane1: {fileID: 0} - plane2: {fileID: 0} - plane3: {fileID: 0} - plane4: {fileID: 0} - plane5: {fileID: 0} + m_Planes: + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} m_Dampen: serializedVersion: 2 minMaxState: 0 @@ -22834,17 +23480,20 @@ ParticleSystem: interiorCollisions: 1 TriggerModule: enabled: 0 - collisionShape0: {fileID: 0} - collisionShape1: {fileID: 0} - collisionShape2: {fileID: 0} - collisionShape3: {fileID: 0} - collisionShape4: {fileID: 0} - collisionShape5: {fileID: 0} + serializedVersion: 2 inside: 1 outside: 0 enter: 0 exit: 0 + colliderQueryMode: 0 radiusScale: 1 + primitives: + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} SubModule: serializedVersion: 2 enabled: 0 @@ -23795,9 +24444,12 @@ ParticleSystemRenderer: m_CastShadows: 1 m_ReceiveShadows: 1 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 + m_RayTracingMode: 0 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -23810,6 +24462,7 @@ ParticleSystemRenderer: m_ProbeAnchor: {fileID: 0} m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 + m_ReceiveGI: 1 m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 @@ -23823,6 +24476,7 @@ ParticleSystemRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_RenderMode: 0 + m_MeshDistribution: 0 m_SortMode: 0 m_MinParticleSize: 0 m_MaxParticleSize: 0.5 @@ -23839,11 +24493,17 @@ ParticleSystemRenderer: m_EnableGPUInstancing: 0 m_ApplyActiveColorSpace: 0 m_AllowRoll: 1 + m_FreeformStretching: 0 + m_RotateWithStretchDirection: 1 m_VertexStreams: 0001030405 m_Mesh: {fileID: 0} m_Mesh1: {fileID: 0} m_Mesh2: {fileID: 0} m_Mesh3: {fileID: 0} + m_MeshWeighting: 1 + m_MeshWeighting1: 1 + m_MeshWeighting2: 1 + m_MeshWeighting3: 1 m_MaskInteraction: 0 --- !u!1 &191648 GameObject: @@ -23858,7 +24518,7 @@ GameObject: - component: {fileID: 2323518} - component: {fileID: 11480676} - component: {fileID: 114121872901766576} - m_Layer: 0 + m_Layer: 25 m_Name: Sun_HighLOD m_TagString: Untagged m_Icon: {fileID: 0} @@ -23875,6 +24535,7 @@ Transform: m_LocalRotation: {x: -0.17884307, y: -0.8438009, z: -0.15270436, w: 0.48238635} m_LocalPosition: {x: -649, y: 412, z: -576} m_LocalScale: {x: 40, y: 40, z: 40} + m_ConstrainProportionsScale: 0 m_Children: - {fileID: 459352} - {fileID: 400078} @@ -23901,9 +24562,12 @@ MeshRenderer: m_CastShadows: 0 m_ReceiveShadows: 0 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -23915,6 +24579,7 @@ MeshRenderer: m_ProbeAnchor: {fileID: 0} m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 + m_ReceiveGI: 1 m_PreserveUVs: 1 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 @@ -23927,6 +24592,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!114 &11480676 MonoBehaviour: m_ObjectHideFlags: 0 @@ -23975,7 +24641,7 @@ GameObject: - component: {fileID: 438068} - component: {fileID: 19885538} - component: {fileID: 19945510} - m_Layer: 0 + m_Layer: 25 m_Name: StarParticles6 m_TagString: Untagged m_Icon: {fileID: 0} @@ -23992,6 +24658,7 @@ Transform: m_LocalRotation: {x: -0.7071068, y: 0, z: 0, w: 0.7071068} m_LocalPosition: {x: 0, y: 15, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 444254} m_RootOrder: 6 @@ -24003,19 +24670,19 @@ ParticleSystem: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 195752} - serializedVersion: 6 + serializedVersion: 8 lengthInSec: 5 simulationSpeed: 1 stopAction: 0 cullingMode: 1 ringBufferMode: 0 ringBufferLoopRange: {x: 0, y: 1} + emitterVelocityMode: 0 looping: 1 prewarm: 1 playOnAwake: 1 useUnscaledTime: 0 autoRandomSeed: 1 - useRigidbodyForVelocity: 1 startDelay: serializedVersion: 2 minMaxState: 0 @@ -24547,6 +25214,7 @@ ParticleSystem: m_RotationOrder: 4 randomizeRotationDirection: 0 maxNumParticles: 1000 + customEmitterVelocity: {x: 0, y: 0, z: 0} size3D: 0 rotation3D: 0 gravityModifier: @@ -25324,6 +25992,7 @@ ParticleSystem: m_NumColorKeys: 2 m_NumAlphaKeys: 2 UVModule: + serializedVersion: 2 enabled: 1 mode: 0 timeMode: 0 @@ -25423,7 +26092,7 @@ ParticleSystem: rowIndex: 0 cycles: 1 uvChannelMask: -1 - randomRow: 1 + rowMode: 1 sprites: - sprite: {fileID: 0} flipU: 0 @@ -26070,6 +26739,62 @@ ParticleSystem: m_PreInfinity: 2 m_PostInfinity: 2 m_RotationOrder: 4 + LifetimeByEmitterSpeedModule: + enabled: 0 + m_Curve: + serializedVersion: 2 + minMaxState: 1 + scalar: 1 + minScalar: 1 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: -0.8 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 0.2 + inSlope: -0.8 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + m_Range: {x: 0, y: 1} ForceModule: enabled: 0 x: @@ -26234,8 +26959,61 @@ ParticleSystem: inWorldSpace: 0 randomizePerFrame: 0 ExternalForcesModule: + serializedVersion: 2 enabled: 0 - multiplier: 1 + multiplierCurve: + serializedVersion: 2 + minMaxState: 0 + scalar: 1 + minScalar: 1 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 influenceFilter: 0 influenceMask: serializedVersion: 2 @@ -27447,19 +28225,20 @@ ParticleSystem: range: {x: 0, y: 1} CollisionModule: enabled: 0 - serializedVersion: 3 + serializedVersion: 4 type: 0 collisionMode: 0 colliderForce: 0 multiplyColliderForceByParticleSize: 0 multiplyColliderForceByParticleSpeed: 0 multiplyColliderForceByCollisionAngle: 1 - plane0: {fileID: 0} - plane1: {fileID: 0} - plane2: {fileID: 0} - plane3: {fileID: 0} - plane4: {fileID: 0} - plane5: {fileID: 0} + m_Planes: + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} m_Dampen: serializedVersion: 2 minMaxState: 0 @@ -27633,17 +28412,20 @@ ParticleSystem: interiorCollisions: 1 TriggerModule: enabled: 0 - collisionShape0: {fileID: 0} - collisionShape1: {fileID: 0} - collisionShape2: {fileID: 0} - collisionShape3: {fileID: 0} - collisionShape4: {fileID: 0} - collisionShape5: {fileID: 0} + serializedVersion: 2 inside: 1 outside: 0 enter: 0 exit: 0 + colliderQueryMode: 0 radiusScale: 1 + primitives: + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} SubModule: serializedVersion: 2 enabled: 0 @@ -28594,9 +29376,12 @@ ParticleSystemRenderer: m_CastShadows: 1 m_ReceiveShadows: 1 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 + m_RayTracingMode: 0 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -28609,6 +29394,7 @@ ParticleSystemRenderer: m_ProbeAnchor: {fileID: 0} m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 + m_ReceiveGI: 1 m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 @@ -28622,6 +29408,7 @@ ParticleSystemRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_RenderMode: 0 + m_MeshDistribution: 0 m_SortMode: 0 m_MinParticleSize: 0 m_MaxParticleSize: 0.5 @@ -28638,9 +29425,15 @@ ParticleSystemRenderer: m_EnableGPUInstancing: 0 m_ApplyActiveColorSpace: 0 m_AllowRoll: 1 + m_FreeformStretching: 0 + m_RotateWithStretchDirection: 1 m_VertexStreams: 0001030405 m_Mesh: {fileID: 0} m_Mesh1: {fileID: 0} m_Mesh2: {fileID: 0} m_Mesh3: {fileID: 0} + m_MeshWeighting: 1 + m_MeshWeighting1: 1 + m_MeshWeighting2: 1 + m_MeshWeighting3: 1 m_MaskInteraction: 0 diff --git a/Assets/Resources/EnvironmentPrefabs/Standard.prefab b/Assets/Resources/EnvironmentPrefabs/Standard.prefab index 453c541329..c8a87dc5c4 100644 --- a/Assets/Resources/EnvironmentPrefabs/Standard.prefab +++ b/Assets/Resources/EnvironmentPrefabs/Standard.prefab @@ -12,7 +12,7 @@ GameObject: - component: {fileID: 3356686} - component: {fileID: 2317658} - component: {fileID: 114108179853941988} - m_Layer: 0 + m_Layer: 25 m_Name: GroundDisk m_TagString: Untagged m_Icon: {fileID: 0} @@ -29,6 +29,7 @@ Transform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: -0, y: -0.5, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 413308} m_RootOrder: 5 @@ -52,9 +53,12 @@ MeshRenderer: m_CastShadows: 0 m_ReceiveShadows: 0 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -66,6 +70,7 @@ MeshRenderer: m_ProbeAnchor: {fileID: 0} m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 + m_ReceiveGI: 1 m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 @@ -78,6 +83,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!114 &114108179853941988 MonoBehaviour: m_ObjectHideFlags: 0 @@ -104,7 +110,7 @@ GameObject: - component: {fileID: 487626} - component: {fileID: 3311816} - component: {fileID: 2300214} - m_Layer: 0 + m_Layer: 25 m_Name: Geo_FloorBackground m_TagString: Untagged m_Icon: {fileID: 0} @@ -121,6 +127,7 @@ Transform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: -0, y: -0.5, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 413308} m_RootOrder: 1 @@ -144,9 +151,12 @@ MeshRenderer: m_CastShadows: 0 m_ReceiveShadows: 0 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -158,6 +168,7 @@ MeshRenderer: m_ProbeAnchor: {fileID: 0} m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 + m_ReceiveGI: 1 m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 @@ -170,6 +181,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!1 &115408 GameObject: m_ObjectHideFlags: 0 @@ -182,7 +194,7 @@ GameObject: - component: {fileID: 19825366} - component: {fileID: 19954150} - component: {fileID: 114527970182492068} - m_Layer: 0 + m_Layer: 25 m_Name: DustMotes m_TagString: Untagged m_Icon: {fileID: 0} @@ -199,6 +211,7 @@ Transform: m_LocalRotation: {x: -0.7071068, y: 0, z: 0, w: 0.7071068} m_LocalPosition: {x: 0, y: 15, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 413308} m_RootOrder: 4 @@ -210,19 +223,19 @@ ParticleSystem: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 115408} - serializedVersion: 6 + serializedVersion: 8 lengthInSec: 5 simulationSpeed: 1 stopAction: 0 cullingMode: 1 ringBufferMode: 0 ringBufferLoopRange: {x: 0, y: 1} + emitterVelocityMode: 0 looping: 1 prewarm: 1 playOnAwake: 1 useUnscaledTime: 0 autoRandomSeed: 1 - useRigidbodyForVelocity: 1 startDelay: serializedVersion: 2 minMaxState: 0 @@ -772,6 +785,7 @@ ParticleSystem: m_RotationOrder: 4 randomizeRotationDirection: 0 maxNumParticles: 1000 + customEmitterVelocity: {x: 0, y: 0, z: 0} size3D: 0 rotation3D: 0 gravityModifier: @@ -1549,6 +1563,7 @@ ParticleSystem: m_NumColorKeys: 2 m_NumAlphaKeys: 2 UVModule: + serializedVersion: 2 enabled: 0 mode: 0 timeMode: 0 @@ -1648,7 +1663,7 @@ ParticleSystem: rowIndex: 0 cycles: 1 uvChannelMask: -1 - randomRow: 1 + rowMode: 1 sprites: - sprite: {fileID: 0} flipU: 0 @@ -2295,6 +2310,62 @@ ParticleSystem: m_PreInfinity: 2 m_PostInfinity: 2 m_RotationOrder: 4 + LifetimeByEmitterSpeedModule: + enabled: 0 + m_Curve: + serializedVersion: 2 + minMaxState: 1 + scalar: 1 + minScalar: 1 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: -0.8 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 0.2 + inSlope: -0.8 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + m_Range: {x: 0, y: 1} ForceModule: enabled: 0 x: @@ -2459,8 +2530,61 @@ ParticleSystem: inWorldSpace: 0 randomizePerFrame: 0 ExternalForcesModule: + serializedVersion: 2 enabled: 0 - multiplier: 1 + multiplierCurve: + serializedVersion: 2 + minMaxState: 0 + scalar: 1 + minScalar: 1 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + - serializedVersion: 3 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + weightedMode: 0 + inWeight: 0.33333334 + outWeight: 0.33333334 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 influenceFilter: 0 influenceMask: serializedVersion: 2 @@ -3672,19 +3796,20 @@ ParticleSystem: range: {x: 0, y: 1} CollisionModule: enabled: 0 - serializedVersion: 3 + serializedVersion: 4 type: 0 collisionMode: 0 colliderForce: 0 multiplyColliderForceByParticleSize: 0 multiplyColliderForceByParticleSpeed: 0 multiplyColliderForceByCollisionAngle: 1 - plane0: {fileID: 0} - plane1: {fileID: 0} - plane2: {fileID: 0} - plane3: {fileID: 0} - plane4: {fileID: 0} - plane5: {fileID: 0} + m_Planes: + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} m_Dampen: serializedVersion: 2 minMaxState: 0 @@ -3858,17 +3983,20 @@ ParticleSystem: interiorCollisions: 1 TriggerModule: enabled: 0 - collisionShape0: {fileID: 0} - collisionShape1: {fileID: 0} - collisionShape2: {fileID: 0} - collisionShape3: {fileID: 0} - collisionShape4: {fileID: 0} - collisionShape5: {fileID: 0} + serializedVersion: 2 inside: 1 outside: 0 enter: 0 exit: 0 + colliderQueryMode: 0 radiusScale: 1 + primitives: + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} + - {fileID: 0} SubModule: serializedVersion: 2 enabled: 0 @@ -4819,9 +4947,12 @@ ParticleSystemRenderer: m_CastShadows: 1 m_ReceiveShadows: 1 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 + m_RayTracingMode: 0 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -4834,6 +4965,7 @@ ParticleSystemRenderer: m_ProbeAnchor: {fileID: 0} m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 + m_ReceiveGI: 1 m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 @@ -4847,6 +4979,7 @@ ParticleSystemRenderer: m_SortingLayer: 0 m_SortingOrder: 0 m_RenderMode: 0 + m_MeshDistribution: 0 m_SortMode: 0 m_MinParticleSize: 0 m_MaxParticleSize: 0.5 @@ -4863,11 +4996,17 @@ ParticleSystemRenderer: m_EnableGPUInstancing: 0 m_ApplyActiveColorSpace: 0 m_AllowRoll: 1 + m_FreeformStretching: 0 + m_RotateWithStretchDirection: 1 m_VertexStreams: 0001030405 m_Mesh: {fileID: 0} m_Mesh1: {fileID: 0} m_Mesh2: {fileID: 0} m_Mesh3: {fileID: 0} + m_MeshWeighting: 1 + m_MeshWeighting1: 1 + m_MeshWeighting2: 1 + m_MeshWeighting3: 1 m_MaskInteraction: 0 --- !u!114 &114527970182492068 MonoBehaviour: @@ -4893,7 +5032,7 @@ GameObject: serializedVersion: 6 m_Component: - component: {fileID: 413308} - m_Layer: 0 + m_Layer: 25 m_Name: Standard m_TagString: Untagged m_Icon: {fileID: 0} @@ -4910,6 +5049,7 @@ Transform: 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_ConstrainProportionsScale: 0 m_Children: - {fileID: 471000} - {fileID: 487626} @@ -4932,7 +5072,7 @@ GameObject: - component: {fileID: 471000} - component: {fileID: 3369048} - component: {fileID: 2332448} - m_Layer: 0 + m_Layer: 25 m_Name: Geo_StandardStage m_TagString: Untagged m_Icon: {fileID: 0} @@ -4949,6 +5089,7 @@ Transform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: -0.25, z: 0} m_LocalScale: {x: 3, y: 0.05, z: 3} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 413308} m_RootOrder: 0 @@ -4972,9 +5113,12 @@ MeshRenderer: m_CastShadows: 1 m_ReceiveShadows: 1 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -4986,6 +5130,7 @@ MeshRenderer: m_ProbeAnchor: {fileID: 0} m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 + m_ReceiveGI: 1 m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 @@ -4998,6 +5143,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!1 &146846 GameObject: m_ObjectHideFlags: 0 @@ -5009,7 +5155,7 @@ GameObject: - component: {fileID: 402588} - component: {fileID: 3342762} - component: {fileID: 2351194} - m_Layer: 0 + m_Layer: 25 m_Name: Geo_FloorForeground m_TagString: Untagged m_Icon: {fileID: 0} @@ -5026,6 +5172,7 @@ Transform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: -0, y: -0.25, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 413308} m_RootOrder: 2 @@ -5049,9 +5196,12 @@ MeshRenderer: m_CastShadows: 0 m_ReceiveShadows: 1 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -5063,6 +5213,7 @@ MeshRenderer: m_ProbeAnchor: {fileID: 0} m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 + m_ReceiveGI: 1 m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 @@ -5075,6 +5226,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!1 &148614 GameObject: m_ObjectHideFlags: 0 @@ -5086,7 +5238,7 @@ GameObject: - component: {fileID: 411736} - component: {fileID: 3363450} - component: {fileID: 2393132} - m_Layer: 0 + m_Layer: 25 m_Name: Geo_Spikes m_TagString: Untagged m_Icon: {fileID: 0} @@ -5103,6 +5255,7 @@ Transform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 0.5, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 413308} m_RootOrder: 3 @@ -5126,9 +5279,12 @@ MeshRenderer: m_CastShadows: 0 m_ReceiveShadows: 0 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -5140,6 +5296,7 @@ MeshRenderer: m_ProbeAnchor: {fileID: 0} m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 + m_ReceiveGI: 1 m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 @@ -5152,6 +5309,7 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} --- !u!1 &195596 GameObject: m_ObjectHideFlags: 0 @@ -5163,7 +5321,7 @@ GameObject: - component: {fileID: 450412} - component: {fileID: 3362728} - component: {fileID: 2379212} - m_Layer: 0 + m_Layer: 25 m_Name: GroundUnderside m_TagString: Untagged m_Icon: {fileID: 0} @@ -5180,6 +5338,7 @@ Transform: m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: -0, y: -0.5, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 413308} m_RootOrder: 6 @@ -5203,9 +5362,12 @@ MeshRenderer: m_CastShadows: 1 m_ReceiveShadows: 1 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 + m_RayTracingMode: 2 + m_RayTraceProcedural: 0 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -5217,6 +5379,7 @@ MeshRenderer: m_ProbeAnchor: {fileID: 0} m_LightProbeVolumeOverride: {fileID: 0} m_ScaleInLightmap: 1 + m_ReceiveGI: 1 m_PreserveUVs: 0 m_IgnoreNormalsForChartDetection: 0 m_ImportantGI: 0 @@ -5229,3 +5392,4 @@ MeshRenderer: m_SortingLayerID: 0 m_SortingLayer: 0 m_SortingOrder: 0 + m_AdditionalVertexStreams: {fileID: 0} diff --git a/Assets/Resources/ScriptExamples/spectator.html b/Assets/Resources/ScriptExamples/spectator.html index 8fb1773f90..3fce6da574 100644 --- a/Assets/Resources/ScriptExamples/spectator.html +++ b/Assets/Resources/ScriptExamples/spectator.html @@ -51,10 +51,11 @@

Spectator Camera:

+


-
+
   diff --git a/Assets/Resources/UnityGLTFSettings.asset b/Assets/Resources/UnityGLTFSettings.asset index b7aaddc95f..78cef5a7f4 100644 --- a/Assets/Resources/UnityGLTFSettings.asset +++ b/Assets/Resources/UnityGLTFSettings.asset @@ -112,6 +112,18 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 5066402b4fbd41e79ab3d7023cca96c5, type: 3} m_Name: MaterialVariantsPlugin m_EditorClassIdentifier: +--- !u!114 &-2913368442722201512 +MonoBehaviour: + m_ObjectHideFlags: 3 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 473c2b5b3de547139304b32beee641e9, type: 3} + m_Name: AnimationPointerImport + m_EditorClassIdentifier: --- !u!114 &-1701294651066981149 MonoBehaviour: m_ObjectHideFlags: 3 @@ -183,6 +195,7 @@ MonoBehaviour: - {fileID: 8372111537548844026} - {fileID: -7716978867629807533} - {fileID: 6916234453510156686} + - {fileID: -2913368442722201512} ExportPlugins: - {fileID: 242952683485160214} - {fileID: -5728475199642485532} @@ -194,7 +207,6 @@ MonoBehaviour: - {fileID: -7373113640993280472} - {fileID: 7420168740226561727} - {fileID: -6755212205620999988} - - {fileID: 8207833083978872644} - {fileID: -682178813687408182} exportNames: 1 exportFullPath: 0 diff --git a/Assets/Scenes/Main.unity b/Assets/Scenes/Main.unity index 55c188aed8..f87d217cad 100644 --- a/Assets/Scenes/Main.unity +++ b/Assets/Scenes/Main.unity @@ -26,7 +26,7 @@ RenderSettings: m_AmbientIntensity: 1 m_AmbientMode: 3 m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} - m_SkyboxMaterial: {fileID: 0} + m_SkyboxMaterial: {fileID: 2100000, guid: 77b09cb82a5ffa94fb37bccf98d2fc84, type: 2} m_HaloStrength: 0.5 m_FlareStrength: 1 m_FlareFadeSpeed: 3 @@ -38,7 +38,7 @@ RenderSettings: m_ReflectionIntensity: 1 m_CustomReflection: {fileID: 8900000, guid: 378efb751ea39e14cb1fd93f49ead278, type: 3} m_Sun: {fileID: 0} - m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} + m_IndirectSpecularColor: {r: 0.49780262, g: 0.49780262, b: 0.49780262, a: 1} m_UseRadianceAmbientProbe: 0 --- !u!157 &4 LightmapSettings: @@ -3683,6 +3683,7 @@ MonoBehaviour: m_EnableGlbVersion2: 1 m_DebugUpload: 1 m_TbtSettings: {fileID: 11400000, guid: 86eb32a1d469be44a99294025e7795de, type: 2} + m_UnityGLTFSettings: {fileID: 1, guid: 4bcbc565b83276a46b0353b376d2a77d, type: 2} m_ReplaceBrushesOnLoad: 0 m_BrushReplacementMap: [] m_IntroSketchUsdFilename: @@ -10743,7 +10744,7 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 59a80c71ac022374fbe28ebb361ab7ee, type: 3} m_Name: m_EditorClassIdentifier: - m_ThumbnailSuffix: s128 + m_ThumbnailSuffix: --- !u!114 &652605562 MonoBehaviour: m_ObjectHideFlags: 0 @@ -10859,6 +10860,7 @@ MonoBehaviour: m_EditorClassIdentifier: m_AssetsPerPage: 20 m_SketchbookRefreshInterval: 10 + m_UseLocalFeaturedSketches: 0 --- !u!114 &652605567 MonoBehaviour: m_ObjectHideFlags: 0 @@ -18638,6 +18640,7 @@ Transform: - {fileID: 1065755966} - {fileID: 1843608204} - {fileID: 1830711222} + - {fileID: 8494983682236033548} m_Father: {fileID: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!114 &1370550524 @@ -22541,6 +22544,58 @@ TextMesh: type: 3} m_PrefabInstance: {fileID: 622614087} m_PrefabAsset: {fileID: 0} +--- !u!1 &1611595290 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1611595291} + - component: {fileID: 1611595292} + m_Layer: 0 + m_Name: IcosaIdentity + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1611595291 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1611595290} + 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_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 669339392} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1611595292 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1611595290} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: e1689780c428aa14ea42c2125e391b45, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Service: 5 + m_OAuthScopes: [] + m_AdditionalDesktopOAuthScopes: [] + m_CallbackPath: /icosa + m_LoggedInTexture: {fileID: 2800000, guid: 0d05cda193064458a9a7bb085905c5a1, type: 3} + m_TokenStorePrefix: IcosaOAuth2 + m_AuthorizationServerUrl: + m_TokenServerUrl: --- !u!1 &1612665327 GameObject: m_ObjectHideFlags: 0 @@ -36858,6 +36913,81 @@ PrefabInstance: insertIndex: -1 addedObject: {fileID: 0} m_SourcePrefab: {fileID: 100100000, guid: e26dd31bb70849e4da9f0b1230a62278, type: 3} +--- !u!1001 &8494983682236033547 +PrefabInstance: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + m_TransformParent: {fileID: 1370550523} + m_Modifications: + - target: {fileID: 2455894836569734632, guid: fd97be770c9e84eb1b5fcc5c06bd0adf, + type: 3} + propertyPath: m_RootOrder + value: 4 + objectReference: {fileID: 0} + - target: {fileID: 2455894836569734632, guid: fd97be770c9e84eb1b5fcc5c06bd0adf, + type: 3} + propertyPath: m_LocalPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2455894836569734632, guid: fd97be770c9e84eb1b5fcc5c06bd0adf, + type: 3} + propertyPath: m_LocalPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2455894836569734632, guid: fd97be770c9e84eb1b5fcc5c06bd0adf, + type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2455894836569734632, guid: fd97be770c9e84eb1b5fcc5c06bd0adf, + type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 2455894836569734632, guid: fd97be770c9e84eb1b5fcc5c06bd0adf, + type: 3} + propertyPath: m_LocalRotation.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2455894836569734632, guid: fd97be770c9e84eb1b5fcc5c06bd0adf, + type: 3} + propertyPath: m_LocalRotation.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2455894836569734632, guid: fd97be770c9e84eb1b5fcc5c06bd0adf, + type: 3} + propertyPath: m_LocalRotation.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2455894836569734632, guid: fd97be770c9e84eb1b5fcc5c06bd0adf, + type: 3} + propertyPath: m_LocalEulerAnglesHint.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2455894836569734632, guid: fd97be770c9e84eb1b5fcc5c06bd0adf, + type: 3} + propertyPath: m_LocalEulerAnglesHint.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2455894836569734632, guid: fd97be770c9e84eb1b5fcc5c06bd0adf, + type: 3} + propertyPath: m_LocalEulerAnglesHint.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 5512400623774099615, guid: fd97be770c9e84eb1b5fcc5c06bd0adf, + type: 3} + propertyPath: m_Name + value: GltfExportStandinManager + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_SourcePrefab: {fileID: 100100000, guid: fd97be770c9e84eb1b5fcc5c06bd0adf, type: 3} +--- !u!4 &8494983682236033548 stripped +Transform: + m_CorrespondingSourceObject: {fileID: 2455894836569734632, guid: fd97be770c9e84eb1b5fcc5c06bd0adf, + type: 3} + m_PrefabInstance: {fileID: 8494983682236033547} + m_PrefabAsset: {fileID: 0} --- !u!4 &9123593761565215834 Transform: m_ObjectHideFlags: 0 @@ -36955,3 +37085,4 @@ SceneRoots: - {fileID: 1802399861} - {fileID: 106206546} - {fileID: 1848773840} + - {fileID: 1611595291} diff --git a/Assets/Scripts/API/ApiManager.cs b/Assets/Scripts/API/ApiManager.cs index 0b90f808a9..228cd26b22 100644 --- a/Assets/Scripts/API/ApiManager.cs +++ b/Assets/Scripts/API/ApiManager.cs @@ -1,878 +1,900 @@ -// Copyright 2021 The Open Brush Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// 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; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Net; -using System.Net.Sockets; -using System.Reflection; -using System.Text; -using System.Threading; -using Newtonsoft.Json; -using UnityEngine; -using UnityEngine.Networking; -using WebSocketServer; - -namespace TiltBrush -{ - public class ApiManager : MonoBehaviour - { - private const string ROOT_API_URL = "/api/v1"; - private const string BASE_USER_SCRIPTS_URL = "/scripts"; - private const string BASE_EXAMPLE_SCRIPTS_URL = "/examplescripts"; - private const string BASE_HTML = @" - -{0}"; - - - private FileSystemWatcher m_FileWatcher; - private string m_UserScriptsPath; - private Queue m_RequestedCommandQueue = Queue.Synchronized(new Queue()); - private Dictionary m_CommandStatuses; - private Queue m_OutgoingCommandQueue = Queue.Synchronized(new Queue()); - private List m_OutgoingApiListeners; - private static ApiManager m_Instance; - private Dictionary endpoints; - private byte[] CameraViewPng; - - private bool cameraViewRequested; - private bool cameraViewGenerated; - - [NonSerialized] public Vector3 BrushOrigin = new(0, 13, 3); // Good origin for monoscopic - [NonSerialized] public Quaternion BrushInitialRotation = Quaternion.LookRotation(Vector3.forward, Vector3.up); - [NonSerialized] public Vector3 BrushPosition; - [NonSerialized] public Quaternion BrushRotation; - public bool ForcePaintingOn = false; - private Dictionary m_UserScripts; - private Dictionary m_ExampleScripts; - - public static ApiManager Instance - { - get { return m_Instance; } - } - [NonSerialized] public Stack<(Vector3, Quaternion)> BrushTransformStack; - [NonSerialized] public Dictionary CommandExamples; - public string m_startupScriptName = "startup.sketchscript"; - - public string UserScriptsPath() { return m_UserScriptsPath; } - - void Awake() - { - m_Instance = this; - m_UserScriptsPath = Path.Combine(App.UserPath(), "Scripts"); - App.HttpServer.AddHttpHandler($"/help", InfoCallback); - App.HttpServer.AddHttpHandler($"/help/commands", InfoCallback); - App.HttpServer.AddHttpHandler($"/help/brushes", InfoCallback); - App.HttpServer.AddRawHttpHandler("/cameraview", CameraViewCallback); - PopulateApi(); - m_UserScripts = new Dictionary(); - m_ExampleScripts = new Dictionary(); - m_CommandStatuses = new Dictionary(); - PopulateExampleScripts(); - PopulateUserScripts(); - BrushTransformStack = new Stack<(Vector3, Quaternion)>(); - ResetBrushTransform(); - if (!Directory.Exists(m_UserScriptsPath)) - { - Directory.CreateDirectory(m_UserScriptsPath); - } - if (Directory.Exists(m_UserScriptsPath)) - { - m_FileWatcher = new FileSystemWatcher(m_UserScriptsPath, "*.html"); - m_FileWatcher.NotifyFilter = NotifyFilters.LastWrite; - m_FileWatcher.Created += OnScriptsDirectoryChanged; - m_FileWatcher.Changed += OnScriptsDirectoryChanged; - // m_FileWatcher.FileDeleted += OnScriptsDirectoryChanged; TODO - m_FileWatcher.EnableRaisingEvents = true; - } - if (CommandExamples == null) - { - CommandExamples = new Dictionary(); - } - CommandExamples["draw.paths"] = "[[0,0,0],[1,0,0],[1,1,0]],[[0,0,-1],[-1,0,-1],[-1,1,-1]]"; - CommandExamples["draw.path"] = "[0,0,0],[1,0,0],[1,1,0],[0,1,0]"; - CommandExamples["draw.stroke"] = "[0,0,0,0,180,90,.75],[1,0,0,0,180,90,.75],[1,1,0,0,180,90,.75],[0,1,0,0,180,90,.75]"; - CommandExamples["listenfor.strokes"] = "http://localhost:8000/"; - CommandExamples["draw.polygon"] = "5,1,0"; - CommandExamples["draw.text"] = "hello"; - CommandExamples["draw.svg"] = "M 184,199 116,170 53,209.6 60,136.2 4.3,88"; - CommandExamples["draw.camerapath"] = "0"; - CommandExamples["brush.type"] = "ink"; - CommandExamples["color.add.hsv"] = "0.1,0.2,0.3"; - CommandExamples["color.add.rgb"] = "0.1,0.2,0.3"; - CommandExamples["color.set.rgb"] = "0.1,0.2,0.3"; - CommandExamples["color.set.hsv"] = "0.1,0.2,0.3"; - CommandExamples["color.set.html"] = "darkblue"; - CommandExamples["brush.size.set"] = ".5"; - CommandExamples["brush.size.add"] = ".1"; - CommandExamples["spectator.move.to"] = "1,1,1"; - CommandExamples["spectator.move.by"] = "1,1,1"; - CommandExamples["spectator.turn.y"] = "45"; - CommandExamples["spectator.turn.x"] = "45"; - CommandExamples["spectator.turn.z"] = "45"; - CommandExamples["spectator.direction"] = "45,45,0"; - CommandExamples["spectator.look.at"] = "1,2,3"; - CommandExamples["spectator.mode"] = "circular"; - CommandExamples["spectator.show"] = "panels"; - CommandExamples["spectator.hide"] = "widgets"; - CommandExamples["user.move.to"] = "1,1,1"; - CommandExamples["user.move.by"] = "1,1,1"; - CommandExamples["brush.move.to"] = "1,1,1"; - CommandExamples["brush.move.by"] = "1,1,1"; - CommandExamples["brush.move"] = "1"; - CommandExamples["brush.draw"] = "1"; - CommandExamples["brush.turn.y"] = "45"; - CommandExamples["brush.turn.x"] = "45"; - CommandExamples["brush.turn.z"] = "45"; - CommandExamples["brush.look.at"] = "1,1,1"; - CommandExamples["stroke.delete"] = "0"; - CommandExamples["stroke.select"] = "0"; - CommandExamples["strokes.select"] = "0,3"; - CommandExamples["selection.trim"] = "2"; - CommandExamples["selection.points.addnoise"] = "x,0.5"; - CommandExamples["selection.points.quantize"] = "0.1"; - CommandExamples["strokes.join"] = "0,2"; - CommandExamples["stroke.add"] = "0"; - CommandExamples["load.user"] = "0"; - CommandExamples["load.curated"] = "0"; - CommandExamples["load.liked"] = "0"; - CommandExamples["load.drive"] = "0"; - CommandExamples["load.named"] = "Untitled_0.tilt"; - CommandExamples["showfolder.sketch"] = "0"; - CommandExamples["import.model"] = "Andy\\Andy.obj"; - CommandExamples["import.image"] = "TiltBrushLogo.png"; - CommandExamples["import.video"] = "animated-logo.mp4"; - App.Instance.StateChanged += RunStartupScript; - } - - public void ResetBrushTransform() - { - // Resets the "turtle" transform back to it's original values - BrushPosition = BrushOrigin; - BrushRotation = BrushInitialRotation; - } - - public void RunStartupScript(App.AppState oldState, App.AppState newState) - { - - if (!(oldState == App.AppState.LoadingBrushesAndLighting && newState == App.AppState.Standard)) return; - - var startupScriptPath = Path.Combine(m_UserScriptsPath, m_startupScriptName); - - if (File.Exists(startupScriptPath)) - { - var lines = File.ReadAllLines(startupScriptPath); - foreach (string pair in lines) - { - EnqueueCommand(pair); - } - } - } - - private class EnqueuedApiCommand - { - private Guid m_Handle; - private string m_Command; - private string m_Parameters; - - public Guid Handle => m_Handle; - public string Command => m_Command; - public string Parameters => m_Parameters; - - public EnqueuedApiCommand(string command, string parameters) - { - m_Handle = Guid.NewGuid(); - m_Command = command; - m_Parameters = parameters; - } - } - - private EnqueuedApiCommand EnqueueCommand(string commandString) - { - if (string.IsNullOrWhiteSpace(commandString)) return null; - if (commandString.StartsWith("//")) return null; - string[] commandPair = commandString.Split(new[] { '=' }, 2); - if (commandPair.Length < 1) return null; - string parameters; - parameters = commandPair.Length == 2 ? UnityWebRequest.UnEscapeURL(commandPair[1]) : ""; - EnqueuedApiCommand cmd = new EnqueuedApiCommand(commandPair[0], parameters); - m_RequestedCommandQueue.Enqueue(cmd); - return cmd; - } - - private void OnScriptsDirectoryChanged(object sender, FileSystemEventArgs e) - { - var fileinfo = new FileInfo(e.FullPath); - RegisterUserScript(fileinfo); - } - - private string InfoCallback(HttpListenerRequest request) - { - string html; - StringBuilder builder; - switch (request.Url.Segments.Last()) - { - case "commands": - - var host = $"{request.LocalEndPoint.Address}:{request.LocalEndPoint.Port}"; - host = host.Replace("127.0.0.1", "localhost"); - - if (request.Url.Query.Contains("raw")) - { - html = String.Join("\n", endpoints.Keys); - } - else if (request.Url.Query.Contains("json")) - { - html = JsonConvert.SerializeObject(ListApiCommands(), Formatting.Indented); - } - else - { - var commandList = ListApiCommandsAsStrings(); - builder = new StringBuilder("

Open Brush API Commands

"); - builder.AppendLine($"

To run commands a request to this url with http://{host}/api/v1?

"); - builder.AppendLine("

Commands are querystring parameters: commandname=parameters

"); - builder.AppendLine("

Separate multiple commands with &

"); - builder.AppendLine($"

Example: http://{host}/api/v1?brush.turn.y=45&brush.draw=1

"); - builder.AppendLine("
"); - foreach (var key in commandList.Keys) - { - string paramList = commandList[key].Item1; - if (paramList != "") - { - paramList = $"({paramList})"; - } - builder.AppendLine($@"
{key} {paramList} - Try it
-
{commandList[key].Item2}

"); - } - builder.AppendLine("
"); - html = String.Format(BASE_HTML, builder); - } - break; - case "brushes": - var brushes = BrushCatalog.m_Instance.AllBrushes.Where(x => x.DurableName != ""); - if (request.Url.Query.Contains("raw")) - { - html = String.Join("\n", brushes.Select(x => x.DurableName)); - } - else - { - builder = new StringBuilder("

Open Brush Brushes

"); - builder.AppendLine("
    "); - foreach (var b in brushes) - { - builder.AppendLine($"
  • {b.DurableName}
  • "); - } - builder.AppendLine("
"); - html = String.Format(BASE_HTML, builder); - } - break; - case "help": - default: - html = $@"

Open Brush API Help

-"; - break; - } - return html; - } - - private string getCommandExample(string key) - { - if (CommandExamples.ContainsKey(key)) - { - return $"{key}={CommandExamples[key]}"; - } - else - { - return key; - } - } - - private void PopulateExampleScripts() - { - App.HttpServer.AddHttpHandler(BASE_EXAMPLE_SCRIPTS_URL, ExampleScriptsCallback); - var exampleScripts = Resources.LoadAll("ScriptExamples", typeof(TextAsset)); - foreach (TextAsset htmlFile in exampleScripts) - { - string filename = $"{BASE_EXAMPLE_SCRIPTS_URL}/{htmlFile.name}.html"; - m_ExampleScripts[filename] = htmlFile.ToString(); - App.HttpServer.AddHttpHandler(filename, ExampleScriptsCallback); - } - } - - private void PopulateUserScripts() - { - App.HttpServer.AddHttpHandler(BASE_USER_SCRIPTS_URL, UserScriptsCallback); - if (!Directory.Exists(m_UserScriptsPath)) - { - Directory.CreateDirectory(m_UserScriptsPath); - } - if (Directory.Exists(m_UserScriptsPath)) - { - var dirInfo = new DirectoryInfo(m_UserScriptsPath); - FileInfo[] AllFileInfo = dirInfo.GetFiles(); - foreach (FileInfo fileinfo in AllFileInfo) - { - RegisterUserScript(fileinfo); - } - } - } - - private void RegisterUserScript(FileInfo file) - { - if (file.Extension == ".html" || file.Extension == ".htm") - { - var f = file.OpenText(); - string filename = $"{BASE_USER_SCRIPTS_URL}/{file.Name}"; - m_UserScripts[filename] = f.ReadToEnd(); - f.Close(); - if (!App.HttpServer.HttpHandlerExists(filename)) - { - App.HttpServer.AddHttpHandler(filename, UserScriptsCallback); - } - } - } - - private void PopulateApi() - { - endpoints = new Dictionary(); - var types = AppDomain.CurrentDomain.GetAssemblies() - .SelectMany(t => t.GetTypes()) - .Where(t => t.IsClass && t.Namespace == "TiltBrush"); - - foreach (var type in types) - { - foreach (MethodInfo methodInfo in type.GetMethods()) - { - var attrs = Attribute.GetCustomAttributes(methodInfo, typeof(ApiEndpoint)); - foreach (Attribute attr in attrs) - { - ApiEndpoint apiEndpoint = (ApiEndpoint)attr; - bool valid = false; - if (type.IsAbstract && type.IsSealed) // therefore is static - { - apiEndpoint.instance = null; - valid = true; - } - else if (type.IsSubclassOf(typeof(MonoBehaviour))) - { - apiEndpoint.instance = FindObjectOfType(type); - if (apiEndpoint.instance != null) - { - valid = true; - } - else - { - Debug.LogWarning($"No instance found for ApiEndpoint on: {type}"); - } - } - - if (valid) - { - apiEndpoint.type = type; - apiEndpoint.methodInfo = methodInfo; - apiEndpoint.parameterInfo = methodInfo.GetParameters(); - endpoints[apiEndpoint.Endpoint] = apiEndpoint; - } - else - { - Debug.LogWarning($"ApiEndpoint declared on invalid class: {type}"); - } - } - } - } - App.HttpServer.AddHttpHandler(ROOT_API_URL, ApiCommandCallback); - } - - private string InvokeEndpoint(EnqueuedApiCommand command) - { - if (endpoints.ContainsKey(command.Command)) - { - var endpoint = endpoints[command.Command]; - var parameters = endpoint.DecodeParams(command.Parameters); - return endpoint.Invoke(parameters)?.ToString(); - } - if (!command.Command.StartsWith("//")) - { - Debug.LogError($"Invalid API command: {command.Command}"); - } - return null; - } - - [ContextMenu("Log Api Commands")] - public void LogCommandsList() - { - if (!Application.isPlaying) - { - Debug.LogError("Please run in play mode"); - } - else - { - var builder = new StringBuilder(); - var commands = ListApiCommandsAsStrings(); - foreach (var k in commands.Keys) - { - builder.AppendLine($"{k} ({commands[k].Item2}): {commands[k].Item2}"); - } - } - } - - Dictionary ListApiCommandsAsStrings() - { - var commandList = new Dictionary(); - foreach (var endpoint in endpoints.Keys) - { - var paramInfoText = new List(); - foreach (var param in endpoints[endpoint].parameterInfo) - { - string typeName = param.ParameterType.Name - .Replace("Single", "float") - .Replace("Int32", "int") - .Replace("String", "string"); - paramInfoText.Add($"{typeName} {param.Name}"); - } - string paramInfo = String.Join(", ", paramInfoText); - commandList[endpoint] = (paramInfo, endpoints[endpoint].Description); - } - return commandList; - } - - Dictionary ListApiCommands() - { - var commandList = new Dictionary(); - foreach (var endpoint in endpoints.Keys) - { - commandList[endpoint] = new - { - parameters = endpoints[endpoint].ParamsAsDict(), - description = endpoints[endpoint].Description - }; - } - return commandList; - } - - private string UserScriptsCallback(HttpListenerRequest request) - { - string html; - if (request.Url.Segments.Length == 2) - { - var builder = new StringBuilder("

Open Brush User Scripts

"); - builder.AppendLine("
    "); - foreach (var e in m_UserScripts) - { - builder.AppendLine($"
  • {e.Key}
  • "); - } - - // Only show this button on Windows - // TODO Update this is ApiMethods.OpenUserFolder is ever cross platform - // (Also see similar global commands that will need updating) - if (Application.platform == RuntimePlatform.WindowsPlayer || Application.platform == RuntimePlatform.WindowsEditor) - { - builder.AppendLine($""); - } - builder.AppendLine("
"); - html = String.Format(BASE_HTML, builder); - } - else - { - html = m_UserScripts[Uri.UnescapeDataString(request.Url.AbsolutePath)]; - } - return ScriptTemplateSubstitution(html); - } - - private string ExampleScriptsCallback(HttpListenerRequest request) - { - string html; - if (request.Url.Segments.Length == 2) - { - var builder = new StringBuilder("

Open Brush Example Scripts

"); - builder.AppendLine("
    "); - foreach (var e in m_ExampleScripts) - { - builder.AppendLine($"
  • {e.Key}
  • "); - } - builder.AppendLine("
"); - html = String.Format(BASE_HTML, builder); - } - else - { - html = m_ExampleScripts[Uri.UnescapeDataString(request.Url.AbsolutePath)]; - } - return ScriptTemplateSubstitution(html); - } - - private string ScriptTemplateSubstitution(string html) - { - - // TODO Document these - - string[] brushNameList = BrushCatalog.m_Instance.AllBrushes - .Where(x => x.Description != "") - .Where(x => x.m_SupersededBy == null) - .Select(x => x.Description.Replace(" ", "").Replace(".", "").Replace("(", "").Replace(")", "")) - .ToArray(); - string brushesJson = JsonConvert.SerializeObject(brushNameList); - html = html.Replace("{{brushesJson}}", brushesJson); - - string pointFamilies = JsonConvert.SerializeObject(Enum.GetNames(typeof(SymmetryGroup.R))); - html = html.Replace("{{pointFamiliesJson}}", pointFamilies); - - string wallpaperGroups = JsonConvert.SerializeObject(Enum.GetNames(typeof(PointSymmetry.Family))); - html = html.Replace("{{wallpaperGroupsJson}}", wallpaperGroups); - - string[] environmentNameList = EnvironmentCatalog.m_Instance.AllEnvironments - .Select(x => x.Description.Replace(" ", "")) - .ToArray(); - string environmentsJson = JsonConvert.SerializeObject(environmentNameList); - html = html.Replace("{{environmentsJson}}", environmentsJson); - - string commandsJson = JsonConvert.SerializeObject(ListApiCommands()); - html = html.Replace("{{commandsJson}}", commandsJson); - - return html; - } - - public void ReceiveWebSocketMessage(WebSocketMessage message) - { - foreach (var cmd in message.data.Split("&")) - { - EnqueueCommand(cmd); - } - } - - string ApiCommandCallback(HttpListenerRequest request) - { - // GET commands - List commandStrings = request.Url.Query.TrimStart('?').Split('&').ToList(); - - // POST commands - if (request.HasEntityBody) - { - using (Stream body = request.InputStream) - { - using (var reader = new StreamReader(body, request.ContentEncoding)) - { - // TODO also accept JSON - var formdata = Uri.UnescapeDataString(reader.ReadToEnd()); - var formdataCommands = formdata.Replace("+", " ").Split('&').Where(s => s.Trim().Length > 0); - commandStrings.AddRange(formdataCommands); - } - } - } - - List responses = new List(); - - foreach (string commandString in commandStrings) - { - if (commandString.StartsWith("query.")) - { - responses.Add(HandleApiQuery(commandString)); - } - else - { - EnqueueCommand(commandString); - } - } - - return String.Join("\n", responses); - } - - private string HandleApiQuery(string commandString) - { - - // API queries are distinct from commands in that they return immediate results and never change the scene - - string[] commandPair = commandString.Split(new[] { '=' }, 2); - if (commandPair.Length < 1) return null; - switch (commandPair[0]) - { - case "query.queue": - return m_OutgoingCommandQueue.Count.ToString(); - case "query.command": - if (m_CommandStatuses.ContainsKey(commandPair[1])) - { - return m_CommandStatuses[commandPair[1]]; - } - else - { - return $"pending"; - } - case "query.spectator.position": - return ApiMainThreadObserver.Instance.SpectatorCamPosition.ToString(); - case "query.spectator.rotation": - return ApiMainThreadObserver.Instance.SpectatorCamRotation.eulerAngles.ToString(); - case "query.spectator.target": - return ApiMainThreadObserver.Instance.SpectatorCamTargetPosition.ToString(); - } - return "unknown query"; - } - - public bool HasOutgoingListeners => m_OutgoingApiListeners != null && m_OutgoingApiListeners.Count > 0; - - public void EnqueueOutgoingCommands(List> commands) - { - if (!HasOutgoingListeners) return; - foreach (var command in commands) - { - m_OutgoingCommandQueue.Enqueue(command); - } - } - - public void AddOutgoingCommandListener(Uri uri) - { - if (m_OutgoingApiListeners == null) m_OutgoingApiListeners = new List(); - if (m_OutgoingApiListeners.Contains(uri)) return; - m_OutgoingApiListeners.Add(uri); - - } - - private void OutgoingApiCommand() - { - if (!HasOutgoingListeners) return; - - KeyValuePair command; - try - { - command = (KeyValuePair)m_OutgoingCommandQueue.Dequeue(); - } - catch (InvalidOperationException) - { - return; - } - - foreach (var listenerUrl in m_OutgoingApiListeners) - { - string getUri = $"{listenerUrl}?{command.Key}={command.Value}"; - if (getUri.Length < 512) // Actually limit is 2083 but let's be conservative - { - StartCoroutine(GetRequest(getUri)); - } - else - { - var formData = new Dictionary - { - {command.Key, command.Value} - }; - StartCoroutine(PostRequest(listenerUrl.ToString(), formData)); - } - } - } - - IEnumerator GetRequest(string uri) - { - using (UnityWebRequest webRequest = UnityWebRequest.Get(uri)) - { - yield return webRequest.SendWebRequest(); - } - } - - IEnumerator PostRequest(string uri, Dictionary formData) - { - using (UnityWebRequest webRequest = UnityWebRequest.Post(uri, formData)) - { - yield return webRequest.SendWebRequest(); - } - } - - private bool HandleApiCommand() - { - EnqueuedApiCommand command; - try - { - command = (EnqueuedApiCommand)m_RequestedCommandQueue.Dequeue(); - } - catch (InvalidOperationException) - { - return false; - } - var result = Instance.InvokeEndpoint(command); - m_CommandStatuses[command.Handle.ToString()] = result; - return true; - } - - private void Update() - { - HandleApiCommand(); - OutgoingApiCommand(); - UpdateCameraView(); - } - - - IEnumerator ScreenCap() - { - yield return new WaitForEndOfFrame(); - var rt = new RenderTexture(Screen.width, Screen.height, 0); - ScreenCapture.CaptureScreenshotIntoRenderTexture(rt); - var oldTex = RenderTexture.active; - var tex = new Texture2D(rt.width, rt.height, TextureFormat.RGB24, false); - RenderTexture.active = rt; - tex.ReadPixels(new Rect(0, 0, tex.width, tex.height), 0, 0); - FlipTextureVertically(tex); - tex.Apply(); - RenderTexture.active = oldTex; - CameraViewPng = tex.EncodeToPNG(); - Destroy(tex); - - cameraViewRequested = false; - cameraViewGenerated = true; - } - - public static void FlipTextureVertically(Texture2D original) - { - // ScreenCap is upside down so flip it - // Orientation might be platform specific so we might need some logic around this - - var originalPixels = original.GetPixels(); - - Color[] newPixels = new Color[originalPixels.Length]; - - int width = original.width; - int rows = original.height; - - for (int x = 0; x < width; x++) - { - for (int y = 0; y < rows; y++) - { - newPixels[x + y * width] = originalPixels[x + (rows - y - 1) * width]; - } - } - - original.SetPixels(newPixels); - original.Apply(); - } - - private void UpdateCameraView() - { - if (cameraViewRequested) StartCoroutine(ScreenCap()); - } - - private HttpListenerContext CameraViewCallback(HttpListenerContext ctx) - { - - cameraViewRequested = true; - while (cameraViewGenerated == false) - { - Thread.Sleep(5); - } - cameraViewGenerated = false; - - ctx.Response.AddHeader("Content-Type", "image/png"); - ctx.Response.ContentLength64 = CameraViewPng.Length; - try - { - if (ctx.Response.OutputStream.CanWrite) - { - ctx.Response.OutputStream.Write(CameraViewPng, 0, CameraViewPng.Length); - } - } - catch (SocketException e) - { - Debug.LogWarning(e.Message); - } - finally - { - ctx.Response.Close(); - } - ctx = null; - return ctx; - } - - public void LoadPolyModel(string assetId) - { - StartCoroutine(SpawnModelCoroutine(assetId, "API")); - } - - public void LoadPolyModel(Uri uri) - { - string assetId = UnityWebRequest.EscapeURL(uri.ToString()); - StartCoroutine(SpawnModelCoroutine(assetId, "API")); - } - - private static IEnumerator SpawnModelCoroutine(string assetId, string reason) - { - // Same as calling Model.RequestModelPreload -> RequestModelLoadInternal, except - // this won't ignore the request if the load-into-memory previously failed. - App.PolyAssetCatalog.RequestModelLoad(assetId, reason); - - // It is possible from this section forward that the user may have moved on to a different page - // on the Poly panel, which is why we use a local copy of 'model' rather than m_Model. - Model model; - // A model in the catalog will become non-null once the gltf has been downloaded or is in the - // cache. - while ((model = App.PolyAssetCatalog.GetModel(assetId)) == null) - { - yield return null; - } - - // A model becomes valid once the gltf has been successfully read into a Unity mesh. - if (!model.m_Valid) - { - // The model might be in the "loaded with error" state, but it seems harmless to try again. - // If the user keeps clicking, we'll keep trying. - yield return model.LoadFullyCoroutine(reason); - Debug.Assert(model.m_Valid || model.Error != null); - } - - if (!model.m_Valid) - { - OutputWindowScript.Error($"Couldn't load model: {model.Error?.message}", model.Error?.detail); - } - else - { - TrTransform xfSpawn = new TrTransform(); - CreateWidgetCommand createCommand = new CreateWidgetCommand( - WidgetManager.m_Instance.ModelWidgetPrefab, xfSpawn, Quaternion.identity, true - ); - SketchMemoryScript.m_Instance.PerformAndRecordCommand(createCommand); - ModelWidget modelWidget = createCommand.Widget as ModelWidget; - modelWidget.Model = model; - modelWidget.Show(true); - createCommand.SetWidgetCost(modelWidget.GetTiltMeterCost()); - - WidgetManager.m_Instance.WidgetsDormant = false; - SketchControlsScript.m_Instance.EatGazeObjectInput(); - SelectionManager.m_Instance.RemoveFromSelection(false); - } - } - - public void HandleStrokeListeners(IEnumerable controlPoints, Guid guid, Color color, float size) - { - if (!HasOutgoingListeners) return; - var pointsAsStrings = new List(); - foreach (var cp in controlPoints) - { - var pos = cp.m_Pos; - var rot = cp.m_Orient.eulerAngles; - pointsAsStrings.Add($"[{pos.x},{pos.y},{pos.z},{rot.x},{rot.y},{rot.z},{cp.m_Pressure}]"); - } - EnqueueOutgoingCommands( - new List> - { - new ("brush.type", guid.ToString()), - new ("brush.size.set", size.ToString()), - new ("color.set.rgb", $"{color.r},{color.g},{color.b}"), - new ("draw.stroke", string.Join(",", pointsAsStrings)) - } - ); - } - } -} +// Copyright 2021 The Open Brush Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// 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; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net; +using System.Net.Sockets; +using System.Reflection; +using System.Text; +using System.Threading; +using Newtonsoft.Json; +using UnityEngine; +using UnityEngine.Networking; +using WebSocketServer; + +namespace TiltBrush +{ + public class ApiManager : MonoBehaviour + { + private const string ROOT_API_URL = "/api/v1"; + private const string BASE_USER_SCRIPTS_URL = "/scripts"; + private const string BASE_EXAMPLE_SCRIPTS_URL = "/examplescripts"; + private const string BASE_HTML = @" + +{0}"; + + + private FileSystemWatcher m_FileWatcher; + private string m_UserScriptsPath; + private Queue m_RequestedCommandQueue = Queue.Synchronized(new Queue()); + private Dictionary m_CommandStatuses; + private Queue m_OutgoingCommandQueue = Queue.Synchronized(new Queue()); + private List m_OutgoingApiListeners; + private static ApiManager m_Instance; + private Dictionary endpoints; + private byte[] CameraViewPng; + + private bool cameraViewRequested; + private bool cameraViewGenerated; + + [NonSerialized] public Vector3 BrushOrigin = new(0, 13, 3); // Good origin for monoscopic + [NonSerialized] public Quaternion BrushInitialRotation = Quaternion.LookRotation(Vector3.forward, Vector3.up); + [NonSerialized] public Vector3 BrushPosition; + [NonSerialized] public Quaternion BrushRotation; + public bool ForcePaintingOn = false; + private Dictionary m_UserScripts; + private Dictionary m_ExampleScripts; + + public static ApiManager Instance + { + get { return m_Instance; } + } + [NonSerialized] public Stack<(Vector3, Quaternion)> BrushTransformStack; + [NonSerialized] public Dictionary CommandExamples; + public string m_startupScriptName = "startup.sketchscript"; + + // Need to set this on the main thread because of localiztion + private string m_BrushesJson; + + public string UserScriptsPath() { return m_UserScriptsPath; } + + void Awake() + { + m_Instance = this; + m_UserScriptsPath = Path.Combine(App.UserPath(), "Scripts"); + App.HttpServer.AddHttpHandler($"/help", InfoCallback); + App.HttpServer.AddHttpHandler($"/help/commands", InfoCallback); + App.HttpServer.AddHttpHandler($"/help/brushes", InfoCallback); + App.HttpServer.AddRawHttpHandler("/cameraview", CameraViewCallback); + PopulateApi(); + + m_UserScripts = new Dictionary(); + m_ExampleScripts = new Dictionary(); + m_CommandStatuses = new Dictionary(); + PopulateExampleScripts(); + PopulateUserScripts(); + BrushTransformStack = new Stack<(Vector3, Quaternion)>(); + ResetBrushTransform(); + + if (!Directory.Exists(m_UserScriptsPath)) + { + Directory.CreateDirectory(m_UserScriptsPath); + } + if (Directory.Exists(m_UserScriptsPath)) + { + m_FileWatcher = new FileSystemWatcher(m_UserScriptsPath, "*.html"); + m_FileWatcher.NotifyFilter = NotifyFilters.LastWrite; + m_FileWatcher.Created += OnScriptsDirectoryChanged; + m_FileWatcher.Changed += OnScriptsDirectoryChanged; + // m_FileWatcher.FileDeleted += OnScriptsDirectoryChanged; TODO + m_FileWatcher.EnableRaisingEvents = true; + } + if (CommandExamples == null) + { + CommandExamples = new Dictionary(); + } + CommandExamples["draw.paths"] = "[[0,0,0],[1,0,0],[1,1,0]],[[0,0,-1],[-1,0,-1],[-1,1,-1]]"; + CommandExamples["draw.path"] = "[0,0,0],[1,0,0],[1,1,0],[0,1,0]"; + CommandExamples["draw.stroke"] = "[0,0,0,0,180,90,.75],[1,0,0,0,180,90,.75],[1,1,0,0,180,90,.75],[0,1,0,0,180,90,.75]"; + CommandExamples["listenfor.strokes"] = "http://localhost:8000/"; + CommandExamples["draw.polygon"] = "5,1,0"; + CommandExamples["draw.text"] = "hello"; + CommandExamples["draw.svg"] = "M 184,199 116,170 53,209.6 60,136.2 4.3,88"; + CommandExamples["draw.camerapath"] = "0"; + CommandExamples["brush.type"] = "ink"; + CommandExamples["color.add.hsv"] = "0.1,0.2,0.3"; + CommandExamples["color.add.rgb"] = "0.1,0.2,0.3"; + CommandExamples["color.set.rgb"] = "0.1,0.2,0.3"; + CommandExamples["color.set.hsv"] = "0.1,0.2,0.3"; + CommandExamples["color.set.html"] = "darkblue"; + CommandExamples["brush.size.set"] = ".5"; + CommandExamples["brush.size.add"] = ".1"; + CommandExamples["spectator.move.to"] = "1,1,1"; + CommandExamples["spectator.move.by"] = "1,1,1"; + CommandExamples["spectator.turn.y"] = "45"; + CommandExamples["spectator.turn.x"] = "45"; + CommandExamples["spectator.turn.z"] = "45"; + CommandExamples["spectator.direction"] = "45,45,0"; + CommandExamples["spectator.look.at"] = "1,2,3"; + CommandExamples["spectator.mode"] = "circular"; + CommandExamples["spectator.show"] = "panels"; + CommandExamples["spectator.hide"] = "widgets"; + CommandExamples["user.move.to"] = "1,1,1"; + CommandExamples["user.move.by"] = "1,1,1"; + CommandExamples["brush.move.to"] = "1,1,1"; + CommandExamples["brush.move.by"] = "1,1,1"; + CommandExamples["brush.move"] = "1"; + CommandExamples["brush.draw"] = "1"; + CommandExamples["brush.turn.y"] = "45"; + CommandExamples["brush.turn.x"] = "45"; + CommandExamples["brush.turn.z"] = "45"; + CommandExamples["brush.look.at"] = "1,1,1"; + CommandExamples["stroke.delete"] = "0"; + CommandExamples["stroke.select"] = "0"; + CommandExamples["strokes.select"] = "0,3"; + CommandExamples["selection.trim"] = "2"; + CommandExamples["selection.points.addnoise"] = "x,0.5"; + CommandExamples["selection.points.quantize"] = "0.1"; + CommandExamples["strokes.join"] = "0,2"; + CommandExamples["stroke.add"] = "0"; + CommandExamples["load.user"] = "0"; + CommandExamples["load.curated"] = "0"; + CommandExamples["load.liked"] = "0"; + CommandExamples["load.drive"] = "0"; + CommandExamples["load.named"] = "Untitled_0.tilt"; + CommandExamples["showfolder.sketch"] = "0"; + CommandExamples["import.model"] = "Andy\\Andy.obj"; + CommandExamples["import.image"] = "TiltBrushLogo.png"; + CommandExamples["import.video"] = "animated-logo.mp4"; + App.Instance.StateChanged += RunStartupScript; + } + + void Start() + { + // HTTP API String substitutions + // Don't move to Awake() as that runs too early + string[] brushNameList = BrushCatalog.m_Instance.GetTagFilteredBrushList() + .Select(ApiFriendlyBrushName) + .ToArray(); + m_BrushesJson = JsonConvert.SerializeObject(brushNameList, Formatting.Indented); + } + + public void ResetBrushTransform() + { + // Resets the "turtle" transform back to it's original values + BrushPosition = BrushOrigin; + BrushRotation = BrushInitialRotation; + } + + public void RunStartupScript(App.AppState oldState, App.AppState newState) + { + + if (!(oldState == App.AppState.LoadingBrushesAndLighting && newState == App.AppState.Standard)) return; + + var startupScriptPath = Path.Combine(m_UserScriptsPath, m_startupScriptName); + + if (File.Exists(startupScriptPath)) + { + var lines = File.ReadAllLines(startupScriptPath); + foreach (string pair in lines) + { + EnqueueCommand(pair); + } + } + } + + private class EnqueuedApiCommand + { + private Guid m_Handle; + private string m_Command; + private string m_Parameters; + + public Guid Handle => m_Handle; + public string Command => m_Command; + public string Parameters => m_Parameters; + + public EnqueuedApiCommand(string command, string parameters) + { + m_Handle = Guid.NewGuid(); + m_Command = command; + m_Parameters = parameters; + } + } + + private EnqueuedApiCommand EnqueueCommand(string commandString) + { + if (string.IsNullOrWhiteSpace(commandString)) return null; + if (commandString.StartsWith("//")) return null; + string[] commandPair = commandString.Split(new[] { '=' }, 2); + if (commandPair.Length < 1) return null; + string parameters; + parameters = commandPair.Length == 2 ? UnityWebRequest.UnEscapeURL(commandPair[1]) : ""; + EnqueuedApiCommand cmd = new EnqueuedApiCommand(commandPair[0], parameters); + m_RequestedCommandQueue.Enqueue(cmd); + return cmd; + } + + private void OnScriptsDirectoryChanged(object sender, FileSystemEventArgs e) + { + var fileinfo = new FileInfo(e.FullPath); + RegisterUserScript(fileinfo); + } + + private string InfoCallback(HttpListenerRequest request) + { + string html; + StringBuilder builder; + switch (request.Url.Segments.Last()) + { + case "commands": + + var host = $"{request.LocalEndPoint.Address}:{request.LocalEndPoint.Port}"; + host = host.Replace("127.0.0.1", "localhost"); + + if (request.Url.Query.Contains("raw")) + { + html = String.Join("\n", endpoints.Keys); + } + else if (request.Url.Query.Contains("json")) + { + html = JsonConvert.SerializeObject(ListApiCommands(), Formatting.Indented); + } + else + { + var commandList = ListApiCommandsAsStrings(); + builder = new StringBuilder("

Open Brush API Commands

"); + builder.AppendLine($"

To run commands a request to this url with http://{host}/api/v1?

"); + builder.AppendLine("

Commands are querystring parameters: commandname=parameters

"); + builder.AppendLine("

Separate multiple commands with &

"); + builder.AppendLine($"

Example: http://{host}/api/v1?brush.turn.y=45&brush.draw=1

"); + builder.AppendLine("
"); + foreach (var key in commandList.Keys) + { + string paramList = commandList[key].Item1; + if (paramList != "") + { + paramList = $"({paramList})"; + } + builder.AppendLine($@"
{key} {paramList} + Try it
+
{commandList[key].Item2}

"); + } + builder.AppendLine("
"); + html = String.Format(BASE_HTML, builder); + } + break; + case "brushes": + var brushes = BrushCatalog.m_Instance.AllBrushes.Where(x => x.DurableName != ""); + if (request.Url.Query.Contains("raw")) + { + html = String.Join("\n", brushes.Select(x => x.DurableName)); + } + else + { + builder = new StringBuilder("

Open Brush Brushes

"); + builder.AppendLine("
    "); + foreach (var b in brushes) + { + builder.AppendLine($"
  • {b.DurableName}
  • "); + } + builder.AppendLine("
"); + html = String.Format(BASE_HTML, builder); + } + break; + case "help": + default: + html = $@"

Open Brush API Help

+"; + break; + } + return html; + } + + private string getCommandExample(string key) + { + if (CommandExamples.ContainsKey(key)) + { + return $"{key}={CommandExamples[key]}"; + } + else + { + return key; + } + } + + private void PopulateExampleScripts() + { + App.HttpServer.AddHttpHandler(BASE_EXAMPLE_SCRIPTS_URL, ExampleScriptsCallback); + var exampleScripts = Resources.LoadAll("ScriptExamples", typeof(TextAsset)); + foreach (TextAsset htmlFile in exampleScripts) + { + string filename = $"{BASE_EXAMPLE_SCRIPTS_URL}/{htmlFile.name}.html"; + m_ExampleScripts[filename] = htmlFile.ToString(); + App.HttpServer.AddHttpHandler(filename, ExampleScriptsCallback); + } + } + + private void PopulateUserScripts() + { + App.HttpServer.AddHttpHandler(BASE_USER_SCRIPTS_URL, UserScriptsCallback); + if (!Directory.Exists(m_UserScriptsPath)) + { + Directory.CreateDirectory(m_UserScriptsPath); + } + if (Directory.Exists(m_UserScriptsPath)) + { + var dirInfo = new DirectoryInfo(m_UserScriptsPath); + FileInfo[] AllFileInfo = dirInfo.GetFiles(); + foreach (FileInfo fileinfo in AllFileInfo) + { + RegisterUserScript(fileinfo); + } + } + } + + private void RegisterUserScript(FileInfo file) + { + if (file.Extension == ".html" || file.Extension == ".htm") + { + var f = file.OpenText(); + string filename = $"{BASE_USER_SCRIPTS_URL}/{file.Name}"; + m_UserScripts[filename] = f.ReadToEnd(); + f.Close(); + if (!App.HttpServer.HttpHandlerExists(filename)) + { + App.HttpServer.AddHttpHandler(filename, UserScriptsCallback); + } + } + } + + private void PopulateApi() + { + endpoints = new Dictionary(); + var types = AppDomain.CurrentDomain.GetAssemblies() + .SelectMany(t => t.GetTypes()) + .Where(t => t.IsClass && t.Namespace == "TiltBrush"); + + foreach (var type in types) + { + foreach (MethodInfo methodInfo in type.GetMethods()) + { + var attrs = Attribute.GetCustomAttributes(methodInfo, typeof(ApiEndpoint)); + foreach (Attribute attr in attrs) + { + ApiEndpoint apiEndpoint = (ApiEndpoint)attr; + bool valid = false; + if (type.IsAbstract && type.IsSealed) // therefore is static + { + apiEndpoint.instance = null; + valid = true; + } + else if (type.IsSubclassOf(typeof(MonoBehaviour))) + { + apiEndpoint.instance = FindObjectOfType(type); + if (apiEndpoint.instance != null) + { + valid = true; + } + else + { + Debug.LogWarning($"No instance found for ApiEndpoint on: {type}"); + } + } + + if (valid) + { + apiEndpoint.type = type; + apiEndpoint.methodInfo = methodInfo; + apiEndpoint.parameterInfo = methodInfo.GetParameters(); + endpoints[apiEndpoint.Endpoint] = apiEndpoint; + } + else + { + Debug.LogWarning($"ApiEndpoint declared on invalid class: {type}"); + } + } + } + } + App.HttpServer.AddHttpHandler(ROOT_API_URL, ApiCommandCallback); + } + + private string InvokeEndpoint(EnqueuedApiCommand command) + { + if (endpoints.ContainsKey(command.Command)) + { + var endpoint = endpoints[command.Command]; + var parameters = endpoint.DecodeParams(command.Parameters); + return endpoint.Invoke(parameters)?.ToString(); + } + if (!command.Command.StartsWith("//")) + { + Debug.LogError($"Invalid API command: {command.Command}"); + } + return null; + } + + [ContextMenu("Log Api Commands")] + public void LogCommandsList() + { + if (!Application.isPlaying) + { + Debug.LogError("Please run in play mode"); + } + else + { + var builder = new StringBuilder(); + var commands = ListApiCommandsAsStrings(); + foreach (var k in commands.Keys) + { + builder.AppendLine($"{k} ({commands[k].Item2}): {commands[k].Item2}"); + } + } + } + + Dictionary ListApiCommandsAsStrings() + { + var commandList = new Dictionary(); + foreach (var endpoint in endpoints.Keys) + { + var paramInfoText = new List(); + foreach (var param in endpoints[endpoint].parameterInfo) + { + string typeName = param.ParameterType.Name + .Replace("Single", "float") + .Replace("Int32", "int") + .Replace("String", "string"); + paramInfoText.Add($"{typeName} {param.Name}"); + } + string paramInfo = String.Join(", ", paramInfoText); + commandList[endpoint] = (paramInfo, endpoints[endpoint].Description); + } + return commandList; + } + + Dictionary ListApiCommands() + { + var commandList = new Dictionary(); + foreach (var endpoint in endpoints.Keys) + { + commandList[endpoint] = new + { + parameters = endpoints[endpoint].ParamsAsDict(), + description = endpoints[endpoint].Description + }; + } + return commandList; + } + + private string UserScriptsCallback(HttpListenerRequest request) + { + string html; + if (request.Url.Segments.Length == 2) + { + var builder = new StringBuilder("

Open Brush User Scripts

"); + builder.AppendLine("
    "); + foreach (var e in m_UserScripts) + { + builder.AppendLine($"
  • {e.Key}
  • "); + } + + // Only show this button on Windows + // TODO Update this is ApiMethods.OpenUserFolder is ever cross platform + // (Also see similar global commands that will need updating) + if (Application.platform == RuntimePlatform.WindowsPlayer || Application.platform == RuntimePlatform.WindowsEditor) + { + builder.AppendLine($""); + } + builder.AppendLine("
"); + html = String.Format(BASE_HTML, builder); + } + else + { + html = m_UserScripts[Uri.UnescapeDataString(request.Url.AbsolutePath)]; + } + return ScriptTemplateSubstitution(html); + } + + private string ExampleScriptsCallback(HttpListenerRequest request) + { + string html; + if (request.Url.Segments.Length == 2) + { + var builder = new StringBuilder("

Open Brush Example Scripts

"); + builder.AppendLine("
    "); + foreach (var e in m_ExampleScripts) + { + builder.AppendLine($"
  • {e.Key}
  • "); + } + builder.AppendLine("
"); + html = String.Format(BASE_HTML, builder); + } + else + { + html = m_ExampleScripts[Uri.UnescapeDataString(request.Url.AbsolutePath)]; + } + return ScriptTemplateSubstitution(html); + } + + private string ScriptTemplateSubstitution(string html) + { + + // TODO Document these + html = html.Replace("{{brushesJson}}", m_BrushesJson); + + string pointFamilies = JsonConvert.SerializeObject(Enum.GetNames(typeof(SymmetryGroup.R)), Formatting.Indented); + html = html.Replace("{{pointFamiliesJson}}", pointFamilies); + + string wallpaperGroups = JsonConvert.SerializeObject(Enum.GetNames(typeof(PointSymmetry.Family)), Formatting.Indented); + html = html.Replace("{{wallpaperGroupsJson}}", wallpaperGroups); + + string[] environmentNameList = EnvironmentCatalog.m_Instance.AllEnvironments + .Select(x => x.Description.Replace(" ", "")) + .ToArray(); + string environmentsJson = JsonConvert.SerializeObject(environmentNameList, Formatting.Indented); + html = html.Replace("{{environmentsJson}}", environmentsJson); + + string commandsJson = JsonConvert.SerializeObject(ListApiCommands(), Formatting.Indented); + html = html.Replace("{{commandsJson}}", commandsJson); + + return html; + } + + public static string ApiFriendlyBrushName(BrushDescriptor brush) + { + if (brush.Description == null) + { + Debug.LogWarning($"Brush {brush.m_DurableName} has no description"); + return ""; + } + return brush.Description + .Replace(" ", "") + .Replace(".", "") + .Replace("(", "") + .Replace(")", ""); + } + + public void ReceiveWebSocketMessage(WebSocketMessage message) + { + foreach (var cmd in message.data.Split("&")) + { + EnqueueCommand(cmd); + } + } + + string ApiCommandCallback(HttpListenerRequest request) + { + // GET commands + List commandStrings = request.Url.Query.TrimStart('?').Split('&').ToList(); + + // POST commands + if (request.HasEntityBody) + { + using (Stream body = request.InputStream) + { + using (var reader = new StreamReader(body, request.ContentEncoding)) + { + // TODO also accept JSON + var formdata = Uri.UnescapeDataString(reader.ReadToEnd()); + var formdataCommands = formdata.Replace("+", " ").Split('&').Where(s => s.Trim().Length > 0); + commandStrings.AddRange(formdataCommands); + } + } + } + + List responses = new List(); + + foreach (string commandString in commandStrings) + { + if (commandString.StartsWith("query.")) + { + responses.Add(HandleApiQuery(commandString)); + } + else + { + EnqueueCommand(commandString); + } + } + + return String.Join("\n", responses); + } + + private string HandleApiQuery(string commandString) + { + + // API queries are distinct from commands in that they return immediate results and never change the scene + + string[] commandPair = commandString.Split(new[] { '=' }, 2); + if (commandPair.Length < 1) return null; + switch (commandPair[0]) + { + case "query.queue": + return m_OutgoingCommandQueue.Count.ToString(); + case "query.command": + if (m_CommandStatuses.ContainsKey(commandPair[1])) + { + return m_CommandStatuses[commandPair[1]]; + } + else + { + return $"pending"; + } + case "query.spectator.position": + return ApiMainThreadObserver.Instance.SpectatorCamPosition.ToString(); + case "query.spectator.rotation": + return ApiMainThreadObserver.Instance.SpectatorCamRotation.eulerAngles.ToString(); + case "query.spectator.target": + return ApiMainThreadObserver.Instance.SpectatorCamTargetPosition.ToString(); + } + return "unknown query"; + } + + public bool HasOutgoingListeners => m_OutgoingApiListeners != null && m_OutgoingApiListeners.Count > 0; + + public void EnqueueOutgoingCommands(List> commands) + { + if (!HasOutgoingListeners) return; + foreach (var command in commands) + { + m_OutgoingCommandQueue.Enqueue(command); + } + } + + public void AddOutgoingCommandListener(Uri uri) + { + if (m_OutgoingApiListeners == null) m_OutgoingApiListeners = new List(); + if (m_OutgoingApiListeners.Contains(uri)) return; + m_OutgoingApiListeners.Add(uri); + + } + + private void OutgoingApiCommand() + { + if (!HasOutgoingListeners) return; + + KeyValuePair command; + try + { + command = (KeyValuePair)m_OutgoingCommandQueue.Dequeue(); + } + catch (InvalidOperationException) + { + return; + } + + foreach (var listenerUrl in m_OutgoingApiListeners) + { + string getUri = $"{listenerUrl}?{command.Key}={command.Value}"; + if (getUri.Length < 512) // Actually limit is 2083 but let's be conservative + { + StartCoroutine(GetRequest(getUri)); + } + else + { + var formData = new Dictionary + { + {command.Key, command.Value} + }; + StartCoroutine(PostRequest(listenerUrl.ToString(), formData)); + } + } + } + + IEnumerator GetRequest(string uri) + { + using (UnityWebRequest webRequest = UnityWebRequest.Get(uri)) + { + yield return webRequest.SendWebRequest(); + } + } + + IEnumerator PostRequest(string uri, Dictionary formData) + { + using (UnityWebRequest webRequest = UnityWebRequest.Post(uri, formData)) + { + yield return webRequest.SendWebRequest(); + } + } + + private bool HandleApiCommand() + { + EnqueuedApiCommand command; + try + { + command = (EnqueuedApiCommand)m_RequestedCommandQueue.Dequeue(); + } + catch (InvalidOperationException) + { + return false; + } + var result = Instance.InvokeEndpoint(command); + m_CommandStatuses[command.Handle.ToString()] = result; + return true; + } + + private void Update() + { + HandleApiCommand(); + OutgoingApiCommand(); + UpdateCameraView(); + } + + + IEnumerator ScreenCap() + { + yield return new WaitForEndOfFrame(); + var rt = new RenderTexture(Screen.width, Screen.height, 0); + ScreenCapture.CaptureScreenshotIntoRenderTexture(rt); + var oldTex = RenderTexture.active; + var tex = new Texture2D(rt.width, rt.height, TextureFormat.RGB24, false); + RenderTexture.active = rt; + tex.ReadPixels(new Rect(0, 0, tex.width, tex.height), 0, 0); + FlipTextureVertically(tex); + tex.Apply(); + RenderTexture.active = oldTex; + CameraViewPng = tex.EncodeToPNG(); + Destroy(tex); + + cameraViewRequested = false; + cameraViewGenerated = true; + } + + public static void FlipTextureVertically(Texture2D original) + { + // ScreenCap is upside down so flip it + // Orientation might be platform specific so we might need some logic around this + + var originalPixels = original.GetPixels(); + + Color[] newPixels = new Color[originalPixels.Length]; + + int width = original.width; + int rows = original.height; + + for (int x = 0; x < width; x++) + { + for (int y = 0; y < rows; y++) + { + newPixels[x + y * width] = originalPixels[x + (rows - y - 1) * width]; + } + } + + original.SetPixels(newPixels); + original.Apply(); + } + + private void UpdateCameraView() + { + if (cameraViewRequested) StartCoroutine(ScreenCap()); + } + + private HttpListenerContext CameraViewCallback(HttpListenerContext ctx) + { + + cameraViewRequested = true; + while (cameraViewGenerated == false) + { + Thread.Sleep(5); + } + cameraViewGenerated = false; + + ctx.Response.AddHeader("Content-Type", "image/png"); + ctx.Response.ContentLength64 = CameraViewPng.Length; + try + { + if (ctx.Response.OutputStream.CanWrite) + { + ctx.Response.OutputStream.Write(CameraViewPng, 0, CameraViewPng.Length); + } + } + catch (SocketException e) + { + Debug.LogWarning(e.Message); + } + finally + { + ctx.Response.Close(); + } + ctx = null; + return ctx; + } + + public void LoadPolyModel(string assetId) + { + StartCoroutine(SpawnModelCoroutine(assetId, "API")); + } + + public void LoadPolyModel(Uri uri) + { + string assetId = UnityWebRequest.EscapeURL(uri.ToString()); + StartCoroutine(SpawnModelCoroutine(assetId, "API")); + } + + private static IEnumerator SpawnModelCoroutine(string assetId, string reason) + { + // Same as calling Model.RequestModelPreload -> RequestModelLoadInternal, except + // this won't ignore the request if the load-into-memory previously failed. + App.IcosaAssetCatalog.RequestModelLoad(assetId, reason); + + // It is possible from this section forward that the user may have moved on to a different page + // on the Poly panel, which is why we use a local copy of 'model' rather than m_Model. + Model model; + // A model in the catalog will become non-null once the gltf has been downloaded or is in the + // cache. + while ((model = App.IcosaAssetCatalog.GetModel(assetId)) == null) + { + yield return null; + } + + // A model becomes valid once the gltf has been successfully read into a Unity mesh. + if (!model.m_Valid) + { + // The model might be in the "loaded with error" state, but it seems harmless to try again. + // If the user keeps clicking, we'll keep trying. + yield return model.LoadFullyCoroutine(reason); + Debug.Assert(model.m_Valid || model.Error != null); + } + + if (!model.m_Valid) + { + OutputWindowScript.Error($"Couldn't load model: {model.Error?.message}", model.Error?.detail); + } + else + { + TrTransform xfSpawn = new TrTransform(); + CreateWidgetCommand createCommand = new CreateWidgetCommand( + WidgetManager.m_Instance.ModelWidgetPrefab, xfSpawn, Quaternion.identity, true + ); + SketchMemoryScript.m_Instance.PerformAndRecordCommand(createCommand); + ModelWidget modelWidget = createCommand.Widget as ModelWidget; + modelWidget.Model = model; + modelWidget.Show(true); + createCommand.SetWidgetCost(modelWidget.GetTiltMeterCost()); + + WidgetManager.m_Instance.WidgetsDormant = false; + SketchControlsScript.m_Instance.EatGazeObjectInput(); + SelectionManager.m_Instance.RemoveFromSelection(false); + } + } + + public void HandleStrokeListeners(IEnumerable controlPoints, Guid guid, Color color, float size) + { + if (!HasOutgoingListeners) return; + var pointsAsStrings = new List(); + foreach (var cp in controlPoints) + { + var pos = cp.m_Pos; + var rot = cp.m_Orient.eulerAngles; + pointsAsStrings.Add($"[{pos.x},{pos.y},{pos.z},{rot.x},{rot.y},{rot.z},{cp.m_Pressure}]"); + } + EnqueueOutgoingCommands( + new List> + { + new ("brush.type", guid.ToString()), + new ("brush.size.set", size.ToString()), + new ("color.set.rgb", $"{color.r},{color.g},{color.b}"), + new ("draw.stroke", string.Join(",", pointsAsStrings)) + } + ); + } + } +} diff --git a/Assets/Scripts/API/ApiMethods.DrawStrokes.cs b/Assets/Scripts/API/ApiMethods.DrawStrokes.cs index 895b7b362c..054c705eb5 100644 --- a/Assets/Scripts/API/ApiMethods.DrawStrokes.cs +++ b/Assets/Scripts/API/ApiMethods.DrawStrokes.cs @@ -26,7 +26,7 @@ public static partial class ApiMethods [ApiEndpoint("draw.paths", "Draws a series of paths at the current brush position [[[x1,y1,z1],[x2,y2,z2], etc...]]. Does not move the brush position")] public static void DrawPaths(string jsonString) { - // TODO Use brush rotation + // TODO Use brush rotation var origin = ApiManager.Instance.BrushPosition; var paths = JsonConvert.DeserializeObject>>>($"[{jsonString}]"); DrawStrokes.MultiPathsToStrokes(paths, origin); @@ -108,14 +108,9 @@ public static void Brush(string brushType) try { brushDescriptor = BrushCatalog.m_Instance.AllBrushes - .First(x => x.Description - .Replace(" ", "") - .Replace(".", "") - .Replace("(", "") - .Replace(")", "") - .ToLower() == brushType); + .First(x => ApiManager.ApiFriendlyBrushName(x).ToLower() == brushType); } - catch (InvalidOperationException e) + catch (InvalidOperationException) { Debug.LogError($"No brush found called: {brushType}"); } @@ -125,10 +120,6 @@ public static void Brush(string brushType) { PointerManager.m_Instance.SetBrushForAllPointers(brushDescriptor); } - else - { - Debug.LogError($"No brush found with the name or guid: {brushType}"); - } } [ApiEndpoint("color.add.hsv", "Adds the supplied values to the current color. Values are hue, saturation and value")] diff --git a/Assets/Scripts/API/ApiMethods.EditableModels.cs b/Assets/Scripts/API/ApiMethods.EditableModels.cs index 06d1ef7411..de8e80ab40 100644 --- a/Assets/Scripts/API/ApiMethods.EditableModels.cs +++ b/Assets/Scripts/API/ApiMethods.EditableModels.cs @@ -13,10 +13,12 @@ // limitations under the License. using System; +using System.Collections.Generic; using System.IO; using System.Linq; using UnityEngine; using System.Threading.Tasks; +using Newtonsoft.Json.Linq; namespace TiltBrush { @@ -39,6 +41,30 @@ public static void ImportWebModel(string url) } var destinationPath = Path.Combine("Models", uri.Host); string filename = _DownloadMediaFileFromUrl(uri, destinationPath); + // Very basic workaround for dependent files like .bin and textures + // TODO + // 1. Handle GLB + // 2. Handle other formats + // 3. Handle zip files + // 4. Create subdirectories for each model + if (ext == "gltf") + { + // Split the url into a base uri and the filename + var baseUri = new Uri(uri, "."); + + var fullLocalPath = Path.Combine(App.ModelLibraryPath(), uri.Host); + + var jsonString = File.ReadAllText(Path.Combine(fullLocalPath, filename)); + JObject jsonObject = JObject.Parse(jsonString); + List externalFiles = jsonObject["buffers"].Select(j => j["uri"].Value()).ToList(); + externalFiles.AddRange(jsonObject["images"].Select(j => j["uri"].Value()).ToList()); + foreach (var externalFile in externalFiles) + { + var newUri = new Uri(baseUri, externalFile); + var subdir = Path.GetDirectoryName(externalFile); + _DownloadMediaFileFromUrl(newUri, Path.Combine(fullLocalPath, subdir)); + } + } ImportModel(Path.Combine(uri.Host, filename)); } diff --git a/Assets/Scripts/API/ApiMethods.GlobalCommands.cs b/Assets/Scripts/API/ApiMethods.GlobalCommands.cs index b415e7aec8..91bf488778 100644 --- a/Assets/Scripts/API/ApiMethods.GlobalCommands.cs +++ b/Assets/Scripts/API/ApiMethods.GlobalCommands.cs @@ -13,6 +13,8 @@ // limitations under the License. using System.IO; +using Org.OpenAPITools.Api; +using Org.OpenAPITools.Client; namespace TiltBrush { @@ -40,13 +42,56 @@ public static void SaveNew() SketchControlsScript.m_Instance.IssueGlobalCommand(rEnum, 1); } - // TODO - // [ApiEndpoint("upload", "Saves the current scene and uploads it to Poly/Icosa")] - // public static void SaveAndUpload() - // { - // var rEnum = SketchControlsScript.GlobalCommands.SaveAndUpload; - // SketchControlsScript.m_Instance.IssueGlobalCommand(rEnum); - // } + [ApiEndpoint("save.as", "Saves the current scene with the given name")] + public static void SaveAs(string filename) + { + var rEnum = SketchControlsScript.GlobalCommands.SaveNew; + SketchControlsScript.m_Instance.IssueGlobalCommand(rEnum, 1); + rEnum = SketchControlsScript.GlobalCommands.RenameSketch; + SketchControlsScript.m_Instance.IssueGlobalCommand(rEnum, 0, (int)SketchSetType.User, sParam: filename); + } + + [ApiEndpoint("icosa.login", "Login to the Icosa Gallery")] + public static void IcosaLogin(string username, string password) + { + var config = new Configuration(); + var loginApi = new LoginApi(VrAssetService.m_Instance.IcosaApiRoot); + config.BasePath = VrAssetService.m_Instance.IcosaApiRoot; + loginApi.Configuration = config; + var token = loginApi.LoginLoginPost(username, password); + App.Instance.IcosaToken = token.AccessToken; + + if (token != null) + { + var usersApi = new UsersApi(VrAssetService.m_Instance.IcosaApiRoot); + config = new Configuration { AccessToken = App.Instance.IcosaToken }; + config.BasePath = VrAssetService.m_Instance.IcosaApiRoot; + usersApi.Configuration = config; + var userData = usersApi.GetUsersMeUsersMeGet(); + + if (userData != null) + { + App.IcosaUserName = userData.Displayname; + App.IcosaUserId = userData.Id; + } + } + } + + [ApiEndpoint("icosa.logout", "Logout of the Icosa Gallery")] + public static void IcosaLogout() + { + App.IcosaUserName = null; + App.IcosaUserId = null; + App.IcosaUserIcon = null; + App.Instance.IcosaToken = null; + } + + [ApiEndpoint("icosa.upload", "Uploads it to the Icosa Gallery")] + public static void IcosaUpload() + { + var rEnum = SketchControlsScript.GlobalCommands.UploadToGenericCloud; + SketchControlsScript.m_Instance.IssueGlobalCommand(rEnum, (int)Cloud.Icosa); + } [ApiEndpoint("export.all", "Exports all the scenes in the users's sketch folder")] public static void ExportAll() @@ -262,8 +307,8 @@ public static void ExportRaw() public static void ShowSketchFolder(int index) { var rEnum = SketchControlsScript.GlobalCommands.ShowSketchFolder; - // TODO 0 is User folder. Do we need to support the other SketchSetTypes? - SketchControlsScript.m_Instance.IssueGlobalCommand(rEnum, index, 0); + // TODO Do we need to support the other SketchSetTypes? + SketchControlsScript.m_Instance.IssueGlobalCommand(rEnum, index, (int)SketchSetType.User); } // TODO Why no "enabled" counterpart? @@ -548,6 +593,13 @@ public static void RecordCameraPath() var rEnum = SketchControlsScript.GlobalCommands.RecordCameraPath; SketchControlsScript.m_Instance.IssueGlobalCommand(rEnum); } + + [ApiEndpoint("camerapath.setactive", "Sets the active camera path")] + public static void SetActiveCameraPath(int index) + { + var widget = _GetActiveCameraPath(index); + WidgetManager.m_Instance.SetCurrentCameraPath(widget); + } } } diff --git a/Assets/Scripts/API/ApiMethods.cs b/Assets/Scripts/API/ApiMethods.cs index bfde2c3f77..4d00ea88c6 100644 --- a/Assets/Scripts/API/ApiMethods.cs +++ b/Assets/Scripts/API/ApiMethods.cs @@ -206,6 +206,9 @@ public static void SpectatorMode(string mode) case "circular": cam.SetMode(DropCamWidget.Mode.Circular); break; + case "camerapath": + cam.SetMode(DropCamWidget.Mode.CameraPath); + break; } } diff --git a/Assets/Scripts/App.cs b/Assets/Scripts/App.cs index c26e70c583..1bdf3b9cd1 100644 --- a/Assets/Scripts/App.cs +++ b/Assets/Scripts/App.cs @@ -116,7 +116,7 @@ public enum AppState public static CanvasScript ActiveCanvas => Scene.ActiveCanvas; - public static PolyAssetCatalog PolyAssetCatalog => m_Instance.m_PolyAssetCatalog; + public static IcosaAssetCatalog IcosaAssetCatalog => m_Instance.m_IcosaAssetCatalog; public static Switchboard Switchboard => m_Instance.m_Switchboard; @@ -132,6 +132,17 @@ public enum AppState public static OAuth2Identity GoogleIdentity => m_Instance.m_GoogleIdentity; public static OAuth2Identity SketchfabIdentity => m_Instance.m_SketchfabIdentity; + public string IcosaToken + { + get => PlayerPrefs.HasKey("IcosaToken") ? PlayerPrefs.GetString("IcosaToken") : null; + set => PlayerPrefs.SetString("IcosaToken", value); + } + public static bool IcosaIsLoggedIn => !string.IsNullOrEmpty(App.Instance.IcosaToken); + + public static string IcosaUserName; + public static string IcosaUserId; + public static Texture IcosaUserIcon; + public static GoogleUserSettings GoogleUserSettings => m_Instance.m_GoogleUserSettings; /// Returns the App instance, or null if the app has not been initialized @@ -154,9 +165,10 @@ public static OAuth2Identity GetIdentity(Cloud cloud) { switch (cloud) { - case Cloud.Poly: return GoogleIdentity; + case Cloud.Google: return GoogleIdentity; case Cloud.Sketchfab: return SketchfabIdentity; - default: throw new InvalidOperationException($"No identity for {cloud}"); + case Cloud.Icosa: throw new InvalidOperationException("Icosa does not use OAuth2"); + default: throw new InvalidOperationException($"No OAuth2 identity for {cloud}"); } } @@ -243,7 +255,7 @@ public static void Log(string msg) private string m_UserPath; private string m_OldUserPath; - private PolyAssetCatalog m_PolyAssetCatalog; + private IcosaAssetCatalog m_IcosaAssetCatalog; private Switchboard m_Switchboard; private BrushColorController m_BrushColorController; private GroupManager m_GroupManager; @@ -537,8 +549,8 @@ void Awake() m_Switchboard = new Switchboard(); m_GroupManager = new GroupManager(); - m_PolyAssetCatalog = GetComponent(); - m_PolyAssetCatalog.Init(); + m_IcosaAssetCatalog = GetComponent(); + m_IcosaAssetCatalog.Init(); m_BrushColorController = GetComponent(); @@ -894,7 +906,7 @@ void Update() } } - m_PolyAssetCatalog.UpdateCatalog(); + m_IcosaAssetCatalog.UpdateCatalog(); //update state switch (m_CurrentAppState) @@ -2354,5 +2366,12 @@ private static void CopySupportFiles() } } + public void LogoutIcosa() + { + IcosaUserName = null; + IcosaUserId = null; + IcosaUserIcon = null; + IcosaToken = null; + } } // class App } // namespace TiltBrush diff --git a/Assets/Scripts/Commands/BreakModelApartCommand.cs b/Assets/Scripts/Commands/BreakModelApartCommand.cs index e0745abc45..19f5e49bbe 100644 --- a/Assets/Scripts/Commands/BreakModelApartCommand.cs +++ b/Assets/Scripts/Commands/BreakModelApartCommand.cs @@ -14,6 +14,7 @@ using System.Collections.Generic; using System.Linq; +using System.Text; using UnityEngine; namespace TiltBrush @@ -67,13 +68,11 @@ bool isValid(Transform node) bool hasValidDirectChildren(Transform node) { if (node.gameObject.activeInHierarchy == false) return false; - int count = 0; foreach (Transform child in node) { - if (!isValid(child)) continue; - count++; + if (isValid(child)) return true; } - return count > 0; + return false; } bool isSubPath(string basePath, string potentialSubPath) @@ -169,13 +168,16 @@ public BreakModelApartCommand(ModelWidget initialWidget, BaseCommand parent = nu private static string GetHierarchyPath(Transform root, Transform obj) { - string path = "/" + obj.name; + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.Insert(0, "/" + obj.name); + while (obj.transform.parent != root) { obj = obj.transform.parent; - path = "/" + obj.name + path; + stringBuilder.Insert(0, "/" + obj.name); } - return path; + + return stringBuilder.ToString(); } protected override void OnRedo() diff --git a/Assets/Scripts/Config.cs b/Assets/Scripts/Config.cs index efadeeb3db..fbb4cb7d9a 100644 --- a/Assets/Scripts/Config.cs +++ b/Assets/Scripts/Config.cs @@ -31,6 +31,7 @@ using System.Linq; using System.Reflection; using UnityEngine; +using UnityGLTF; #if OCULUS_SUPPORTED using Unity.XR.Oculus; @@ -209,6 +210,7 @@ public bool IsMobileHardware [Tooltip("Causes the temporary Upload directory to be kept around (Editor only)")] public bool m_DebugUpload; public TiltBrushToolkit.TbtSettings m_TbtSettings; + public GLTFSettings m_UnityGLTFSettings; [Header("Loading")] public bool m_ReplaceBrushesOnLoad; diff --git a/Assets/Scripts/Export/Export.cs b/Assets/Scripts/Export/Export.cs index 7f08b8acf3..3961f1c967 100644 --- a/Assets/Scripts/Export/Export.cs +++ b/Assets/Scripts/Export/Export.cs @@ -1,324 +1,333 @@ -// Copyright 2020 The Tilt Brush Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// 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.IO; -using System.Linq; -using UnityEngine; -using UnityEngine.Localization.Settings; -using UnityGLTF; - -namespace TiltBrush -{ - - public static class Export - { - const string kExportDocumentationUrl = "https://docs.google.com/document/d/11ZsHozYn9FnWG7y3s3WAyKIACfbfwb4PbaS8cZ_xjvo#heading=h.im5f33smiavy"; -#if UNITY_ANDROID || UNITY_IOS - const string kExportReadmeName = "README.txt"; - const string kExportReadmeBody = "Please see " + kExportDocumentationUrl; -#else - const string kExportReadmeName = "README.url"; - const string kExportReadmeBody = @"[InternetShortcut] -URL=" + kExportDocumentationUrl; -#endif - const string kExportSuccess = "EXPORT_SUCCESS"; - - // Returns a writable name for the export file, creating any directories as necessary; - // or null on failure. - private static string MakeExportPath(string parent, string basename, string ext) - { - string child = FileUtils.GenerateNonexistentFilename(parent, basename: ext, extension: ""); - if (!FileUtils.InitializeDirectoryWithUserError( - child, "Failed to create export directory for " + ext)) - { - return null; - } - - return Path.Combine(child, string.Format("{0}.{1}", basename, ext)); - } - - // A helper for managing our progress bar - class Progress - { - private Dictionary m_workAmount = new Dictionary(); - private float m_totalWork = 0.001f; // avoids divide-by-zero - private float m_completedWork = 0; - - public Progress() - { - OverlayManager.m_Instance.UpdateProgress(0); - } - - // If you call SetWork with a non-zero value, you shoud also eventually call CompleteWork - public void SetWork(string name, float effort = 1) - { - if (!m_workAmount.ContainsKey(name)) - { - m_workAmount[name] = effort; - m_totalWork += effort; - } - else - { - Debug.LogErrorFormat("Added {0} twice", name); - } - } - - // It's ok to call CompleteWork with a name you haven't yet set; it's a no-op. - public void CompleteWork(string name) - { - float work; - m_workAmount.TryGetValue(name, out work); - m_completedWork += work; - OverlayManager.m_Instance.UpdateProgress(m_completedWork / m_totalWork); - } - } - - public class AutoTimer : IDisposable - { - private System.Diagnostics.Stopwatch timer = new System.Diagnostics.Stopwatch(); - private string m_tag; - public AutoTimer(string tag) - { - m_tag = tag; - timer.Start(); - } - public void Dispose() - { - timer.Stop(); - Debug.LogFormat("{0} time: {1}s", m_tag, timer.ElapsedMilliseconds / 1000.0f); - } - } - - static bool IsExportEnabled(string format) - { - // I couldn't figure out how to get the default value from the config file for a dictionary with a getter/setter - // so I'm handling defaults here. - var formats = App.UserConfig.Export.Formats; - if (formats == null) - { - formats = new Dictionary - { - { "fbx", true }, - { "glb", true }, - { "newglb", false }, - { "json", false }, - { "latk", false }, - { "obj", true }, - { "stl", false }, - { "usd", false }, - { "wrl", false }, - }; - } - return formats.GetValueOrDefault(format); - } - - public static void ExportScene() - { - var current = SaveLoadScript.m_Instance.SceneFile; - string safeHumanName = FileUtils.SanitizeFilename(current.HumanName); - string basename = FileUtils.SanitizeFilename( - (current.Valid && (safeHumanName != "")) ? safeHumanName : "Untitled"); - - string parent = FileUtils.GenerateNonexistentFilename(App.UserExportPath(), basename, ""); - if (!FileUtils.InitializeDirectoryWithUserError( - parent, "Failed to create export directory")) return; - - // Set up progress bar. - var progress = new Progress(); - if (App.PlatformConfig.EnableExportJson && IsExportEnabled("json")) - { - progress.SetWork("json"); - } -#if FBX_SUPPORTED - if (App.PlatformConfig.EnableExportFbx && IsExportEnabled("fbx")) - { - progress.SetWork("fbx"); - } - if (IsExportEnabled("obj")) - { - progress.SetWork("obj"); - } -#endif - -#if USD_SUPPORTED - if (App.PlatformConfig.EnableExportUsd && IsExportEnabled("usd")) - { - progress.SetWork("usd"); - } -#endif - - if (IsExportEnabled("latk")) - { - progress.SetWork("latk"); - } - - if (IsExportEnabled("wrl")) - { - progress.SetWork("wrl"); - } - - if (IsExportEnabled("stl")) - { - progress.SetWork("stl"); - } - - if (App.PlatformConfig.EnableExportGlb) - { - if (IsExportEnabled("glb")) { progress.SetWork("glb"); } - if (IsExportEnabled("newglb")) { progress.SetWork("newglb"); } - } - - string filename; - - if (App.PlatformConfig.EnableExportJson && IsExportEnabled("json") && - (filename = MakeExportPath(parent, basename, "json")) != null) - { - using (var unused = new AutoTimer("raw export")) - { - OverlayManager.m_Instance.UpdateProgress(0.1f); - ExportRaw.Export(filename); - - // Also write the metadata that would normally go in the .tilt file - SketchSnapshot.ExportMetadata(filename.Replace(".json", ".metadata.json")); - } - progress.CompleteWork("json"); - } - -#if FBX_SUPPORTED - if (App.PlatformConfig.EnableExportFbx && IsExportEnabled("fbx") && - (filename = MakeExportPath(parent, basename, "fbx")) != null) - { - using (var unused = new AutoTimer("fbx export")) - { - OverlayManager.m_Instance.UpdateProgress(0.3f); - ExportFbx.Export(filename, - App.UserConfig.Export.ExportBinaryFbx ? ExportFbx.kFbxBinary : ExportFbx.kFbxAscii, - App.UserConfig.Export.ExportFbxVersion); - OverlayManager.m_Instance.UpdateProgress(0.5f); - } - progress.CompleteWork("fbx"); - } - - if (IsExportEnabled("obj") && App.PlatformConfig.EnableExportFbx && - (filename = MakeExportPath(parent, basename, "obj")) != null) - { - // This has never been tested with the new fbx export style and may not work - ExportFbx.Export(filename, ExportFbx.kObj); - progress.CompleteWork("obj"); - } -#endif - -#if USD_SUPPORTED - if (App.PlatformConfig.EnableExportUsd && IsExportEnabled("usd") && - (filename = MakeExportPath(parent, basename, "usd")) != null) - { - using (var unused = new AutoTimer("usd export")) - { - ExportUsd.ExportPayload(filename); - } - progress.CompleteWork("usd"); - } -#endif - - if (IsExportEnabled("latk") && - (filename = MakeExportPath(parent, basename, "latk")) != null) - { - using (var unused = new AutoTimer("latk export")) - { - ExportLatk.Export(filename); - } - progress.CompleteWork("latk"); - } - - if (IsExportEnabled("wrl") && - (filename = MakeExportPath(parent, basename, "wrl")) != null) - { - ExportVrml.Export(filename); - progress.CompleteWork("wrl"); - } - - if (IsExportEnabled("stl") && - (filename = MakeExportPath(parent, basename, "stl")) != null) - { - try - { - ExportStl.Export(filename); - } - catch (ArgumentOutOfRangeException e) - { - OutputWindowScript.Error("STL export failed", e.Message); - } - progress.CompleteWork("stl"); - } - - if (App.PlatformConfig.EnableExportGlb && IsExportEnabled("glb")) - { - string extension = App.Config.m_EnableGlbVersion2 ? "glb" : "glb1"; - int gltfVersion = App.Config.m_EnableGlbVersion2 ? 2 : 1; - filename = MakeExportPath(parent, basename, extension); - if (filename != null) - { - using (var unused = new AutoTimer("glb export")) - { - OverlayManager.m_Instance.UpdateProgress(0.6f); - - // TBT doesn't need (or want) brush textures in the output because it replaces all - // the materials, so it's fine to keep those http:. However, Sketchfab doesn't support - // http textures so if uploaded, this glb will have missing textures. - var exporter = new ExportGlTF(); - exporter.ExportBrushStrokes( - filename, AxisConvention.kGltf2, binary: true, doExtras: false, - includeLocalMediaContent: true, - gltfVersion: gltfVersion, - selfContained: true - ); - } - } - progress.CompleteWork("glb"); - } - - if (App.PlatformConfig.EnableExportGlb && IsExportEnabled("newglb")) - { - string extension = "glb"; - using (var unused = new AutoTimer("glb export")) - { - OverlayManager.m_Instance.UpdateProgress(0.7f); - var settings = GLTFSettings.GetOrCreateSettings(); - settings.UseMainCameraVisibility = false; - var context = new ExportContext - { - ExportLayers = LayerMask.GetMask("MainCanvas") - }; - var layers = App.Scene.LayerCanvases.Select(x => x.transform).ToArray(); - var unityGltfexporter = new GLTFSceneExporter(layers, context); - unityGltfexporter.SaveGLB(Path.Combine(parent, $"newglb"), $"{basename}.{extension}"); - } - progress.CompleteWork("newglb"); - } - - OutputWindowScript.m_Instance.CreateInfoCardAtController( - InputManager.ControllerName.Brush, basename + - $" {LocalizationSettings.StringDatabase.GetLocalizedString(kExportSuccess)}"); - ControllerConsoleScript.m_Instance.AddNewLine("Located in " + App.UserExportPath()); - - string readmeFilename = Path.Combine(App.UserExportPath(), kExportReadmeName); - if (!File.Exists(readmeFilename) && !Directory.Exists(readmeFilename)) - { - File.WriteAllText(readmeFilename, kExportReadmeBody); - } - } - } -} // namespace TiltBrush +// Copyright 2020 The Tilt Brush Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// 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.IO; +using System.Linq; +using UnityEngine; +using UnityEngine.Localization.Settings; +using UnityGLTF; + +namespace TiltBrush +{ + + public static class Export + { + const string kExportDocumentationUrl = "https://docs.google.com/document/d/11ZsHozYn9FnWG7y3s3WAyKIACfbfwb4PbaS8cZ_xjvo#heading=h.im5f33smiavy"; +#if UNITY_ANDROID || UNITY_IOS + const string kExportReadmeName = "README.txt"; + const string kExportReadmeBody = "Please see " + kExportDocumentationUrl; +#else + const string kExportReadmeName = "README.url"; + const string kExportReadmeBody = @"[InternetShortcut] +URL=" + kExportDocumentationUrl; +#endif + const string kExportSuccess = "EXPORT_SUCCESS"; + + // Returns a writable name for the export file, creating any directories as necessary; + // or null on failure. + private static string MakeExportPath(string parent, string basename, string ext) + { + string child = FileUtils.GenerateNonexistentFilename(parent, basename: ext, extension: ""); + if (!FileUtils.InitializeDirectoryWithUserError( + child, "Failed to create export directory for " + ext)) + { + return null; + } + + return Path.Combine(child, string.Format("{0}.{1}", basename, ext)); + } + + // A helper for managing our progress bar + class Progress + { + private Dictionary m_workAmount = new Dictionary(); + private float m_totalWork = 0.001f; // avoids divide-by-zero + private float m_completedWork = 0; + + public Progress() + { + OverlayManager.m_Instance.UpdateProgress(0); + } + + // If you call SetWork with a non-zero value, you shoud also eventually call CompleteWork + public void SetWork(string name, float effort = 1) + { + if (!m_workAmount.ContainsKey(name)) + { + m_workAmount[name] = effort; + m_totalWork += effort; + } + else + { + Debug.LogErrorFormat("Added {0} twice", name); + } + } + + // It's ok to call CompleteWork with a name you haven't yet set; it's a no-op. + public void CompleteWork(string name) + { + float work; + m_workAmount.TryGetValue(name, out work); + m_completedWork += work; + OverlayManager.m_Instance.UpdateProgress(m_completedWork / m_totalWork); + } + } + + public class AutoTimer : IDisposable + { + private System.Diagnostics.Stopwatch timer = new System.Diagnostics.Stopwatch(); + private string m_tag; + public AutoTimer(string tag) + { + m_tag = tag; + timer.Start(); + } + public void Dispose() + { + timer.Stop(); + Debug.LogFormat("{0} time: {1}s", m_tag, timer.ElapsedMilliseconds / 1000.0f); + } + } + + static bool IsExportEnabled(string format) + { + // I couldn't figure out how to get the default value from the config file for a dictionary with a getter/setter + // so I'm handling defaults here. + var formats = App.UserConfig.Export.Formats; + if (formats == null) + { + formats = new Dictionary + { + { "fbx", true }, + { "glb", true }, + { "newglb", false }, + { "json", false }, + { "latk", false }, + { "obj", true }, + { "stl", false }, + { "usd", false }, + { "wrl", false }, + }; + } + return formats.GetValueOrDefault(format); + } + + public static void ExportScene() + { + var current = SaveLoadScript.m_Instance.SceneFile; + string safeHumanName = FileUtils.SanitizeFilename(current.HumanName); + string basename = FileUtils.SanitizeFilename( + (current.Valid && (safeHumanName != "")) ? safeHumanName : "Untitled"); + + string parent = FileUtils.GenerateNonexistentFilename(App.UserExportPath(), basename, ""); + if (!FileUtils.InitializeDirectoryWithUserError( + parent, "Failed to create export directory")) return; + + // Set up progress bar. + var progress = new Progress(); + if (App.PlatformConfig.EnableExportJson && IsExportEnabled("json")) + { + progress.SetWork("json"); + } +#if FBX_SUPPORTED + if (App.PlatformConfig.EnableExportFbx && IsExportEnabled("fbx")) + { + progress.SetWork("fbx"); + } + if (IsExportEnabled("obj")) + { + progress.SetWork("obj"); + } +#endif + +#if USD_SUPPORTED + if (App.PlatformConfig.EnableExportUsd && IsExportEnabled("usd")) + { + progress.SetWork("usd"); + } +#endif + + if (IsExportEnabled("latk")) + { + progress.SetWork("latk"); + } + + if (IsExportEnabled("wrl")) + { + progress.SetWork("wrl"); + } + + if (IsExportEnabled("stl")) + { + progress.SetWork("stl"); + } + + if (App.PlatformConfig.EnableExportGlb) + { + if (IsExportEnabled("glb")) { progress.SetWork("glb"); } + if (IsExportEnabled("newglb")) { progress.SetWork("newglb"); } + } + + string filename; + + if (App.PlatformConfig.EnableExportJson && IsExportEnabled("json") && + (filename = MakeExportPath(parent, basename, "json")) != null) + { + using (var unused = new AutoTimer("raw export")) + { + OverlayManager.m_Instance.UpdateProgress(0.1f); + ExportRaw.Export(filename); + + // Also write the metadata that would normally go in the .tilt file + SketchSnapshot.ExportMetadata(filename.Replace(".json", ".metadata.json")); + } + progress.CompleteWork("json"); + } + +#if FBX_SUPPORTED + if (App.PlatformConfig.EnableExportFbx && IsExportEnabled("fbx") && + (filename = MakeExportPath(parent, basename, "fbx")) != null) + { + using (var unused = new AutoTimer("fbx export")) + { + OverlayManager.m_Instance.UpdateProgress(0.3f); + ExportFbx.Export(filename, + App.UserConfig.Export.ExportBinaryFbx ? ExportFbx.kFbxBinary : ExportFbx.kFbxAscii, + App.UserConfig.Export.ExportFbxVersion); + OverlayManager.m_Instance.UpdateProgress(0.5f); + } + progress.CompleteWork("fbx"); + } + + if (IsExportEnabled("obj") && App.PlatformConfig.EnableExportFbx && + (filename = MakeExportPath(parent, basename, "obj")) != null) + { + // This has never been tested with the new fbx export style and may not work + ExportFbx.Export(filename, ExportFbx.kObj); + progress.CompleteWork("obj"); + } +#endif + +#if USD_SUPPORTED + if (App.PlatformConfig.EnableExportUsd && IsExportEnabled("usd") && + (filename = MakeExportPath(parent, basename, "usd")) != null) + { + using (var unused = new AutoTimer("usd export")) + { + ExportUsd.ExportPayload(filename); + } + progress.CompleteWork("usd"); + } +#endif + + if (IsExportEnabled("latk") && + (filename = MakeExportPath(parent, basename, "latk")) != null) + { + using (var unused = new AutoTimer("latk export")) + { + ExportLatk.Export(filename); + } + progress.CompleteWork("latk"); + } + + if (IsExportEnabled("wrl") && + (filename = MakeExportPath(parent, basename, "wrl")) != null) + { + ExportVrml.Export(filename); + progress.CompleteWork("wrl"); + } + + if (IsExportEnabled("stl") && + (filename = MakeExportPath(parent, basename, "stl")) != null) + { + try + { + ExportStl.Export(filename); + } + catch (ArgumentOutOfRangeException e) + { + OutputWindowScript.Error("STL export failed", e.Message); + } + progress.CompleteWork("stl"); + } + + if (App.PlatformConfig.EnableExportGlb && IsExportEnabled("glb")) + { + // Legacy GLTF export + string extension = App.Config.m_EnableGlbVersion2 ? "glb" : "glb1"; + int gltfVersion = App.Config.m_EnableGlbVersion2 ? 2 : 1; + filename = MakeExportPath(parent, basename, extension); + if (filename != null) + { + using (var unused = new AutoTimer("glb export")) + { + OverlayManager.m_Instance.UpdateProgress(0.6f); + + // TBT doesn't need (or want) brush textures in the output because it replaces all + // the materials, so it's fine to keep those http:. However, Sketchfab doesn't support + // http textures so if uploaded, this glb will have missing textures. + var exporter = new ExportGlTF(); + exporter.ExportBrushStrokes( + filename, AxisConvention.kGltf2, binary: true, doExtras: true, + includeLocalMediaContent: true, + gltfVersion: gltfVersion, + selfContained: true + ); + } + } + progress.CompleteWork("glb"); + } + + if (App.PlatformConfig.EnableExportGlb && IsExportEnabled("newglb")) + { + // 'New' GLTF export using UnityGLTF + string extension = "glb"; + using (var unused = new AutoTimer("glb export")) + { + OverlayManager.m_Instance.UpdateProgress(0.7f); + var settings = App.Config.m_UnityGLTFSettings; + var context = new ExportContext(settings); + + // Beware the two meanings of "layer" in the following code - Unity layers and Open Brush layers + + var layerCanvases = App.Scene.LayerCanvases.Select(x => x.transform).ToList(); + var layerMask = LayerMask.GetMask("MainCanvas"); + if (App.UserConfig.Export.ExportEnvironment) + { + layerCanvases.Add(App.Instance.m_EnvironmentTransform); + layerMask |= LayerMask.GetMask("Environment"); + } + context.ExportLayers = layerMask; + var unityGltfexporter = new GLTFSceneExporter(layerCanvases.ToArray(), context); + + unityGltfexporter.SaveGLB(Path.Combine(parent, $"newglb"), $"{basename}.{extension}"); + } + progress.CompleteWork("newglb"); + } + + OutputWindowScript.m_Instance.CreateInfoCardAtController( + InputManager.ControllerName.Brush, basename + + $" {LocalizationSettings.StringDatabase.GetLocalizedString(kExportSuccess)}"); + ControllerConsoleScript.m_Instance.AddNewLine("Located in " + App.UserExportPath()); + + string readmeFilename = Path.Combine(App.UserExportPath(), kExportReadmeName); + if (!File.Exists(readmeFilename) && !Directory.Exists(readmeFilename)) + { + File.WriteAllText(readmeFilename, kExportReadmeBody); + } + } + } +} // namespace TiltBrush diff --git a/Assets/Scripts/Export/ExportGlTF.cs b/Assets/Scripts/Export/ExportGlTF.cs index 293ce00c90..32644618fb 100644 --- a/Assets/Scripts/Export/ExportGlTF.cs +++ b/Assets/Scripts/Export/ExportGlTF.cs @@ -193,6 +193,9 @@ private void SetExtras( Color skyColorB = payload.env.skyColorB; Vector3 skyGradientDir = payload.env.skyGradientDir; + // var camPose = SketchControlsScript.m_Instance.GetSaveIconTool().LastSaveCameraRigState.GetLossyTrTransform(); + var pose = App.Scene.Pose; + // Scene-level extras: exporter.G.extras["TB_EnvironmentGuid"] = payload.env.guid.ToString("D"); exporter.G.extras["TB_Environment"] = payload.env.description; @@ -205,9 +208,17 @@ private void SetExtras( exporter.G.extras["TB_FogColor"] = CommaFormattedFloatRGB(payload.env.fogColor); exporter.G.extras["TB_FogDensity"] = payload.env.fogDensity.ToString(); - // TODO: remove when Poly starts using the new color data - exporter.G.extras["TB_SkyColorHorizon"] = CommaFormattedFloatRGB(skyColorA); - exporter.G.extras["TB_SkyColorZenith"] = CommaFormattedFloatRGB(skyColorB); + exporter.G.extras["TB_AmbientLightColor"] = CommaFormattedFloatRGB(payload.lights.ambientColor); + exporter.G.extras["TB_SceneLight0Color"] = CommaFormattedFloatRGB(payload.lights.lights[0].lightColor); + exporter.G.extras["TB_SceneLight0Rotation"] = CommaFormattedVector3( + payload.lights.lights[0].xform.rotation.eulerAngles); + exporter.G.extras["TB_SceneLight1Color"] = CommaFormattedFloatRGB(payload.lights.lights[1].lightColor); + exporter.G.extras["TB_SceneLight1Rotation"] = CommaFormattedVector3( + payload.lights.lights[1].xform.rotation.eulerAngles); + + exporter.G.extras["TB_PoseTranslation"] = CommaFormattedVector3(pose.translation); + exporter.G.extras["TB_PoseRotation"] = CommaFormattedVector3(pose.rotation.eulerAngles); + exporter.G.extras["TB_PoseScale"] = pose.scale; } // Returns a GlTF_Node; null means "there is no node for this group". diff --git a/Assets/Scripts/Export/ExportUtils.cs b/Assets/Scripts/Export/ExportUtils.cs index 1a4fdd42df..a704cc01e5 100644 --- a/Assets/Scripts/Export/ExportUtils.cs +++ b/Assets/Scripts/Export/ExportUtils.cs @@ -1,872 +1,872 @@ -// Copyright 2020 The Tilt Brush Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// 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.Collections.Generic; -using System; -using System.IO; -using System.Linq; -using JetBrains.Annotations; -using UnityEngine; - -namespace TiltBrush -{ - - using TexcoordInfo = GeometryPool.TexcoordInfo; - using Semantic = GeometryPool.Semantic; - using StrokeGroup = SketchGroupTag; - - public static class ExportUtils - { - // Used to refer to built-in textures that we put in Support/ - public const string kBuiltInPrefix = "tiltbrush://"; - public const string kShaderDirectory = "shaders/brushes"; - public const string kProjectRelativeBrushExportRoot = "Support/TiltBrush.com/" + kShaderDirectory; - public const string kProjectRelativeEnvironmentExportRoot = "Support/TiltBrush.com/environments"; - public const string kProjectRelativeTextureExportRoot = "Support/TiltBrush.com/textures"; - public const string kProjectRelativeSupportBrushTexturesRoot = "Support/" + kShaderDirectory; - - // -------------------------------------------------------------------------------------------- // - // Brush/Canvas Export Payloads - // -------------------------------------------------------------------------------------------- // - - /// A canvas and some strokes - [UsedImplicitly(ImplicitUseTargetFlags.Members)] - public class ExportCanvas - { - public CanvasScript m_canvas; - private List m_strokes; - - public ExportCanvas(CanvasScript canvas, IEnumerable strokes) - { - m_canvas = canvas; - m_strokes = strokes.ToList(); - } - - public ExportCanvas(IGrouping group) - { - m_canvas = group.Key; - m_strokes = group.ToList(); - } - - public IEnumerable SplitByGroup() - { - return m_strokes.GroupBy(stroke => stroke.Group) - .Select(g => new ExportGroup(g)); - } - - public IEnumerable SplitByBrush() - { - return m_strokes.GroupBy(stroke => stroke.m_BrushGuid) - .Select(g => new ExportBrush(g)); - } - } - - /// A group id and some strokes - public class ExportGroup - { - public StrokeGroup m_group; - private List m_strokes; - - public ExportGroup(IGrouping group) - { - m_group = group.Key; - m_strokes = group.ToList(); - } - - public IEnumerable SplitByBrush() - { - return m_strokes.GroupBy(stroke => stroke.m_BrushGuid) - .Select(g => new ExportBrush(g)); - } - } - - /// A brush guid and some strokes - /// This is the only grouping that can be converted to geometry - public class ExportBrush - { - public BrushDescriptor m_desc; - private List m_strokes; - - public ExportBrush(IGrouping group) - { - m_desc = BrushCatalog.m_Instance.GetBrush(group.Key); - m_strokes = group.ToList(); - } - - public struct PoolAndStrokes - { - public GeometryPool pool; - public List strokes; - } - - // Returns a pool, or null if it's not from a pool. - private static GeometryPool GetPool(Stroke stroke) - { - if (stroke.m_BatchSubset == null) { return null; } - return stroke.m_BatchSubset.m_ParentBatch.Geometry; - } - - // Yields strokes in the same order as in the input, but adds an additional side effect: - // When the user consumes the stroke they will likely force its batch to become resident. - // This wrapper undoes that, preserving the state of the Batch's residency. - private IEnumerable - PreserveBatchResidency(IEnumerable input) - { - // We could do the "make it resident, make it not resident" dance on a stroke-by-stroke - // basis, but that would be ridiculously wasteful. Optimize by grouping adjacent strokes - // together if they share the same batch. - // - // When a sketch first loads, this optimization works extremely well because batches are - // contiguous in the stroke list. The more the user mutates (select, unselect, recolor) - // the less this will be true. There's not a lot we can do about it unless we want to - // sort the strokes by batch rather than by draw time (or whatever criteria the incoming - // iterator uses), which I think would be too invasive. - foreach (IGrouping group in - input.GroupBy(stroke => GetPool(stroke))) - { - GeometryPool pool = group.Key; - - // If we have to bring the pool into memory, save off enough data so we can - // push it back out. - Mesh previousBackingMesh = null; - if (pool != null && !pool.IsGeometryResident) - { - previousBackingMesh = pool.GetBackingMesh(); - // We currently only eject batch-owned GeometryPool to Mesh, so this is unlikely to trip; - // but we eventually may want to eject them to disk to save even more memory. - if (previousBackingMesh == null) - { - Debug.LogWarning("Not yet able to eject pool back to file; leaving it in memory"); - } - pool.EnsureGeometryResident(); - } - - foreach (Stroke stroke in group) - { - yield return stroke; - } - - if (previousBackingMesh != null) - { - pool.MakeGeometryNotResident(previousBackingMesh); - } - } - } - - // Puts the passed timestamp data into pool.texcoord2. - // It's assumed that the pool does not already have anything in texcoord2. - private static void AugmentWithTimestamps(GeometryPool pool, ref List timestamps) - { - if (App.UserConfig.Export.ExportStrokeTimestamp) - { - GeometryPool.VertexLayout withTxc2 = pool.Layout; - if (withTxc2.texcoord2.size == 0 && timestamps.Count == pool.NumVerts) - { - withTxc2.texcoord2 = new TexcoordInfo { size = 3, semantic = Semantic.Timestamp }; - pool.Layout = withTxc2; - pool.m_Texcoord2.v3 = timestamps; - timestamps = null; // don't let caller reuse the list - } - else - { - Debug.LogError("Internal error; cannot add timestamps"); - } - } - } - - // Appends timestamp data to the passed List. - // - // The timestamps are laid out like so: - // x = start of stroke - // y = end of stroke - // z = Roughly interpolated between the start and end of the stroke - // I say "roughly interpolated" because we make the assumption that each control point - // creates a fixed number of vertices. It's correct only to a first approximation. - private static void AppendTimestamps( - Stroke stroke, int numVerts, - List timestamps) - { - Vector3 ts = new Vector3(stroke.HeadTimestampMs * .001f, - stroke.TailTimestampMs * .001f, - 0); - foreach (float interpolated in MathUtils.LinearResampleCurve( - stroke.m_ControlPoints.Select(cp => cp.m_TimestampMs * .001f).ToArray(), - numVerts)) - { - ts.z = interpolated; - timestamps.Add(ts); - } - } - - /// Converts strokes to multiple GeometryPools whose size is <= vertexLimit. - /// The default vertexLimit is the maximum size allowed by Unity. - /// If a single stroke exceeds the vertex limit, the stroke will be ignored. - /// TODO: dangerous! vertexLimit should be a soft limit, with a hard limit of 65k - public IEnumerable ToGeometryBatches(int vertexLimit = 65534) - { - var layout = BrushCatalog.m_Instance.GetBrush(m_desc.m_Guid).VertexLayout; - var pool = new GeometryPool(); - var strokes = new List(); - // Timestamps are kept separate and only stitched in when we emit a Pool. - // This is because GeometryPool.Append() doesn't know what to do if the - // source and dest layouts are different. - List timestamps = new List(); - pool.Layout = layout; - foreach (var stroke in PreserveBatchResidency(m_strokes)) - { - while (true) - { - if (!stroke.IsGeometryEnabled) { continue; } - int oldNumVerts = pool.NumVerts; - if (pool.Append(stroke, vertexLimit)) - { - strokes.Add(stroke); - if (App.UserConfig.Export.ExportStrokeTimestamp) - { - AppendTimestamps(stroke, pool.NumVerts - oldNumVerts, timestamps); - } - // common case: it fits - break; - } - else if (pool.m_Vertices.Count > 0) - { - // it doesn't fit, but we can make a bit of forward progress by flushing the buffer - AugmentWithTimestamps(pool, ref timestamps); - yield return new PoolAndStrokes { pool = pool, strokes = strokes }; - pool = new GeometryPool(); - pool.Layout = layout; - strokes = new List(); - timestamps = new List(); - // loop around for another go - } - else - { - // very uncommon case: stroke won't fit even in an empty buffer. - // Should never happen with the default vertexLimit. - Debug.LogWarning("Cannot export stroke that exceeds vertex limit"); - // No choice but to ignore the stroke - break; - } - } - } - if (pool.m_Vertices.Count > 0) - { - AugmentWithTimestamps(pool, ref timestamps); - yield return new PoolAndStrokes { pool = pool, strokes = strokes }; - } - } - } - - // -------------------------------------------------------------------------------------------- // - // SceneState Export Payloads - // The state objects below are pure-state populated by the ExportCollector. - // -------------------------------------------------------------------------------------------- // - - // GetInstanceID() is not determinstic. - // The order in which objects are exported is somewhat determinstic. - // This class uses the order of export to determine the id. - public class DeterministicIdGenerator - { - private Dictionary m_instanceIdToId = new Dictionary(); - private int m_nextAvailable = 1; - public int GetIdFromInstanceId(UnityEngine.Object obj) - { - int instanceId = obj.GetInstanceID(); - if (m_instanceIdToId.ContainsKey(instanceId)) - { - return m_instanceIdToId[instanceId]; - } - else - { - var ret = m_nextAvailable; - m_nextAvailable += 1; - m_instanceIdToId[instanceId] = ret; - return ret; - } - } - } - /// The current exportable SceneState of Open Brush. - public class SceneStatePayload - { - // Metadata. - public string generator = "Tilt Brush 23.3.841faedfb compatible (Actually: Open Brush {0}.{1})"; - public DeterministicIdGenerator idGenerator = new DeterministicIdGenerator(); - - // Space Bases. - public readonly AxisConvention axes; - public readonly bool reverseWinding; - public readonly float exportUnitsFromAppUnits = App.UNITS_TO_METERS; - - // Entity Manifests. - public EnvPayload env = new EnvPayload(); - public LightsPayload lights = new LightsPayload(); - public List groups = new List(); - public GroupIdMapping groupIdMapping = new GroupIdMapping(); - // These actually contain the model/image data - public List modelMeshes = new List(); - public List imageQuads = new List(); - // These are bare nodes representing things that we currently can't export - public List referenceThings = new List(); - public readonly string temporaryDirectory = null; - - // If you pass a temporary directory, it may (or may not) be used - // for memory optimizations during the export. In this case, take - // care to call Destroy() if you want the payload to clean up after itself. - public SceneStatePayload(AxisConvention axes, string temporaryDirectory) - { - this.axes = axes; - this.temporaryDirectory = temporaryDirectory; - // The determinant can be used to detect if the basis-change has a mirroring. - // This matters because a mirroring turns the triangles inside-out, requiring - // us to flip their winding to preserve the surface orientation. - this.reverseWinding = (GetFromUnity_Axes(this).determinant < 0); - } - - // Tears down the payload as safely as possible; throws no exceptions - public void Destroy() - { - if (groups != null) - { - foreach (var item in groups) - { - item.Destroy(); - } - } - if (modelMeshes != null) - { - foreach (var item in modelMeshes) - { - item.Destroy(); - } - } - } - } - - // This should be deprecated in favor of putting a group id in all the payloads - public class GroupPayload - { - public UInt32 id; - public List brushMeshes = new List(); - public void Destroy() - { - if (brushMeshes != null) - { - foreach (var item in brushMeshes) - { - item.Destroy(); - } - } - } - } - - public class EnvPayload - { - public Guid guid; - public string description; - public Cubemap skyCubemap; - public bool useGradient; - public Color skyColorA; - public Color skyColorB; - public Vector3 skyGradientDir; - public Color fogColor; - public float fogDensity; - } - - public class LightPayload - { - public LightType type; - public string legacyUniqueName; // guaranteed unique but maybe not friendly - public string name; - public Color lightColor; - public Matrix4x4 xform; - } - - [UsedImplicitly(ImplicitUseTargetFlags.Members)] - public class LightsPayload - { - public Color ambientColor; // currently unused - public List lights = new List(); - } - - // Common to all MeshPayload. - // This is an _instance_ of a mesh, and corresponds to a GameObject/MeshRenderer - public abstract class BaseMeshPayload - { - // A unique not-very-human-readable string. - // "nodeName" and "geometryName" are _mostly_ unique except in edge cases like two distinct - // widgets having the same GetExportName(). - // Keeping this around also means I can diff vs old gltf1 files for testing purposes. - public string legacyUniqueName; - - // A pleasant-looking name for the node - public string nodeName; - public Matrix4x4 xform = Matrix4x4.identity; - // Not owned by this instance; ownership is potentially shared with other BaseMeshPayloads - public GeometryPool geometry; - // A pleasant-looking name for the geometry - public string geometryName; - public IExportableMaterial exportableMaterial; - - public readonly UInt32 group; - - protected BaseMeshPayload(uint groupId) { this.group = groupId; } - - /// Returns a string used to keep different models from having overlapping names. - /// Examples uses: - /// - Keep texture names from colliding - /// - Keep material names from colliding -- in particular this is an issue for - /// the name "defaultShadingGroup" which shows up in Poly-obj and Media Library-obj - /// imports a lot. - public abstract string MeshNamespace { get; } - - // Danger! This destroys resources shared by the entire SceneStatePayload. - // It is only public so it can be called during SceneStatePayload shutdown. - public void Destroy() - { - if (geometry != null) - { - geometry.Destroy(); - geometry = null; - } - } - } - - public class ImageQuadPayload : BaseMeshPayload - { - public override string MeshNamespace => "media"; - public ImageQuadPayload(uint groupId) : base(groupId) { } - } - - // MeshPayload for a poly or media library model; might also be used for - // exporting environments from the editor? - public class ModelMeshPayload : BaseMeshPayload - { - public Model model; - - // Enumerates the instances of a Model in the scene. - // Group by (model, modelId) to collect payloads from the same instance. - public int modelId; - - // These next two are base.xform in factored form: parentXform * localXform == base.xform - - // The transform of the parent ModelWidget. - // Payloads with the same model and modelId come from the same parent, - // therefore they have the same parentXform. - public Matrix4x4 parentXform; - - // This is slightly redundant because it's the same as instanceXform.inverse * base.xform. - // It's stored explicitly for slight added precision. - public Matrix4x4 localXform; - - public override string MeshNamespace - { - get - { - if (model.GetLocation().GetLocationType() == Model.Location.Type.PolyAssetId) - { - return model.AssetId; // blows up if type is not PolyAssetId - } - else - { - string path = Path.GetFileNameWithoutExtension(model.RelativePath); - return System.Text.RegularExpressions.Regex.Replace( - path, @"[^a-zA-Z0-9_-]+", ""); - } - } - } - public ModelMeshPayload(uint groupId) : base(groupId) { } - } - - // MeshPayload for something drawn with a brush. - // Strokes are currently only used when exporting to USD - public class BrushMeshPayload : BaseMeshPayload - { - public List strokes; - public override string MeshNamespace => "brush"; - public BrushMeshPayload(uint groupId) : base(groupId) { } - } - - public class XformPayload - { - public readonly UInt32 group; - // This name isn't (currently) guaranteed to be unique among XformPayloads - public string name; - public Matrix4x4 xform; - - public XformPayload(uint groupId) { this.group = groupId; } - } - - // -------------------------------------------------------------------------------------------- // - // Data Collection Helpers - // -------------------------------------------------------------------------------------------- // - - /// Filters and returns geometry in a convenient format for export. - /// Returns geometry for the main canvas - public static ExportCanvas ExportMainCanvas() - { - // This is probably the more-useful one; it assumes we only have - // one interesting canvas (true, from a user perspective) and merges - // the selection canvas into its target canvas. - // - // It makes the assumption that the selection canvas is not playing - // fast-and-loose, and keeps its transform identical to its target - // canvas (ie, its transform is always identity). - // - // Of course, the selection canvas does play fast-and-loose, but - // we smack the canvas into place (via a deselect/reselect) before - // getting here. - var allowedBrushGuids = new HashSet( - BrushCatalog.m_Instance.AllBrushes - .Where(b => b.m_AllowExport) - .Select(b => (Guid)b.m_Guid)); - var main = App.Scene.MainCanvas; - var selection = App.Scene.SelectionCanvas; - var mainStrokes = SketchMemoryScript.AllStrokes() - .Where(stroke => allowedBrushGuids.Contains(stroke.m_BrushGuid) && - stroke.IsGeometryEnabled && - (stroke.Canvas == main || stroke.Canvas == selection)); - return new ExportCanvas(main, mainStrokes.ToList()); - } - - // Same as ExportAllCanvases but pretends all strokes are on the main canvas - // Does NOT transform strokes so ensure all canvases have identity transforms - public static ExportCanvas ExportAllCanvasesIgnoreLayers() - { - var allowedBrushGuids = new HashSet( - BrushCatalog.m_Instance.AllBrushes - .Where(b => b.m_AllowExport) - .Select(b => (Guid)b.m_Guid)); - var main = App.Scene.MainCanvas; - var selection = App.Scene.SelectionCanvas; - var mainStrokes = SketchMemoryScript - .AllStrokes() - .Where(stroke => allowedBrushGuids.Contains(stroke.m_BrushGuid) && stroke.IsGeometryEnabled); - return new ExportCanvas(main, mainStrokes.ToList()); - } - - /// Filters and returns geometry in a convenient format for export. - public static List ExportAllCanvases() - { - var allowedBrushGuids = new HashSet( - BrushCatalog.m_Instance.AllBrushes - .Where(b => b.m_AllowExport) - .Select(b => (Guid)b.m_Guid)); - - return SketchMemoryScript.AllStrokes() - .Where(stroke => allowedBrushGuids.Contains(stroke.m_BrushGuid) && - stroke.IsGeometryEnabled) - .GroupBy(stroke => stroke.Canvas) - .Select(canvasStrokes => new ExportCanvas(canvasStrokes)) - .ToList(); - } - - // -------------------------------------------------------------------------------------------- // - // Functional Conversion Helpers - // -------------------------------------------------------------------------------------------- // - - /// Applies change-of-basis conversions and distance conversions to a GeometryPool. - public static void ConvertUnitsAndChangeBasis(GeometryPool pool, SceneStatePayload payload) - { - ConvertScaleAndChangeBasis(pool, payload.exportUnitsFromAppUnits, GetFromUnity_Axes(payload)); - } - - private static void ConvertScaleAndChangeBasis( - GeometryPool pool, - float unitChange, - Matrix4x4 basisChange) - { - // If there's translation, it's ambiguous whether scale is applied before or after - // (probably the user means after, but still) - Debug.Assert((Vector3)basisChange.GetColumn(3) == Vector3.zero); - Matrix4x4 basisAndUnitChange = Matrix4x4.Scale(unitChange * Vector3.one) * basisChange; - -#if false // this code is pendantic but is useful to describe what's _really_ going on here - // xfBivector is the transform to use for normals, tangents, and other cross-products. - // Extracting rotation from a mat4 is hard, so take advantage of the fact that basisChange - // is a (maybe improper) rotation, an improper rotation being a rotation with scale -1. - // Matrix4x4 xfBivector = ExtractRotation(basisAndUnitChange); - Matrix4x4 xfBivector = basisChange; - if (basisChange.determinant < 0) { - // remove the -1 uniform scale by giving it yet more -1 uniform scale. - xfBivector = Matrix4x4.Scale(-Vector3.one) * xfBivector; - } - - // The exporter flips triangle winding when handedness flips, but it leaves the job unfinished; - // it needs to also flip the normals and tangents, since they're calculated from cross products. - // Detect that and kludge in an extra -1 scale to finish the job. - if (basisChange.determinant < 0) { - xfBivector = Matrix4x4.Scale(-Vector3.one) * xfBivector; - } -#else - Matrix4x4 xfBivector = basisChange; // The mirroring and the winding-flip cancel each other out -#endif - pool.ApplyTransform(basisAndUnitChange, xfBivector, unitChange, 0, pool.NumVerts); - } - - /// Convert the vertex colors to linear - public static List ConvertToLinearColorspace(List srgb) - { - return new List(srgb.Select(c32 => ((Color)c32).linear)); - } - - public static void ConvertToSrgbColorspace(Color[] linear) - { - for (int i = 0; i < linear.Length; i++) - { - linear[i] = linear[i].gamma; - } - } - - // Unused and untested -#if false - /// Convert the vertex Color32s to linear - /// Beware that you will lose information when quantizing down from - /// linear-float32 to linear-uint8. - public static void ConvertToLinearColorspace(MeshPayload meshes) { - for (int i = 0; i < meshes.Count; i++) { - var pool = meshes.geometry[i]; - for (int j = 0; j < pool.m_Colors.Count; j++) { - pool.m_Colors[j] = ((Color)pool.m_Colors[j]).linear; - } - } - } - /// Convert the light colors to linear - /// Beware that you will lose information when quantizing down from - /// linear-float32 to linear-uint8. - public static void ConvertToLinearColorspace(LightPayload lights) { - // XXX: these values can be > 1 because they are pre-multiplied by intensity - // Is it more appropriate to convert the base color from sRGB -> Linear, - // _then_ multiply by intensity? - lights.ambientColor = lights.ambientColor.linear; - for (int i = 0; i < lights.Count; i++) { - lights.lightColor[i] = lights.lightColor[i].linear; - } - } - /// Convert the environment (sky/fog) colors to linear - public static void ConvertToLinearColorspace(EnvPayload env) { - env.fogColor = env.fogColor.linear; - env.skyColorA = env.skyColorA.linear; - env.skyColorB = env.skyColorB.linear; - } -#endif - - - /// Flips winding order by swapping indices indexA and indexB. - /// indexA and indexB must be in the range [0, 2] and not equal to each other. - public static void ReverseTriangleWinding(GeometryPool pool, int indexA, int indexB) - { - if (indexA == indexB || indexA < 0 || indexA > 2) - { - throw new ArgumentException("indexA"); - } - if (indexB < 0 || indexB > 2) - { - throw new ArgumentException("indexB"); - } - var tris = pool.m_Tris; - int count = tris.Count; - for (int i = 0; i < count; i += 3) - { - var tmp = tris[i + indexA]; - tris[i + indexA] = tris[i + indexB]; - tris[i + indexB] = tmp; - } - } - - /// Given a transform, returns that transform in another basis. - /// The new basis is specified by outputFromInput. - public static Matrix4x4 ChangeBasis( - Matrix4x4 xfInput, - Matrix4x4 outputFromInput, Matrix4x4 inputFromOutput) - { - return outputFromInput * xfInput * inputFromOutput; - } - - /// Given a transform, returns that transform in another basis. - /// The new basis is specified by outputFromInput. - /// - /// Not guaranteed to work if the change-of-basis matrix has non-uniform - /// scale. Otherwise, the resulting transform will not "fit" in a TrTransform. - public static TrTransform ChangeBasis( - TrTransform xfInput, - Matrix4x4 outputFromInput, Matrix4x4 inputFromOutput) - { - // It might make this a little more accurate if outputFromInput were a TrTransform. - // Although... outputFromInput and inputFromOutput expressed as Matrix4x4 are always - // infinitely precise, for axis convention changes at least. Doing the same with a quat - // might involve sqrt(2)s. But maybe not for the common case of unity -> fbx / gltf? - Matrix4x4 m = outputFromInput * xfInput.ToMatrix4x4() * inputFromOutput; - return TrTransform.FromMatrix4x4(m); - } - - /// Given a transform, returns that transform in another basis. - /// The new basis is specified by outputFromInput. - /// - /// Not guaranteed to work if the change-of-basis matrix has non-axis-aligned - /// scale, or if the rotation portion can't be expressed as the product of 90 degree - /// rotations about an axis. Otherwise, the resulting scale will not "fit" in a Vec3. - public static void ChangeBasis( - Vector3 inputTranslation, Quaternion inputRotation, Vector3 inputScale, - out Vector3 translation, out Quaternion rotation, out Vector3 scale, - Matrix4x4 outputFromInput, Matrix4x4 inputFromOutput) - { - TrTransform output = ChangeBasis( - TrTransform.TR(inputTranslation, inputRotation), - outputFromInput, inputFromOutput); - translation = output.translation; - rotation = output.rotation; - // Scale is a bit trickier. - Matrix4x4 m = outputFromInput * Matrix4x4.Scale(inputScale) * inputFromOutput; - scale = new Vector3(m[0, 0], m[1, 1], m[2, 2]); - m[0, 0] = m[1, 1] = m[2, 2] = 1; - Debug.Assert(m.isIdentity); - } - - /// Given a TrTransform, returns that transform as a mat4 in another basis. - /// The new basis is specified by the payload. - /// This changes both axes and units. - public static Matrix4x4 ChangeBasis( - TrTransform xfInput, SceneStatePayload payload) - { - Matrix4x4 basis = AxisConvention.GetFromUnity(payload.axes); - Matrix4x4 basisInverse = AxisConvention.GetToUnity(payload.axes); - return ChangeBasis(xfInput, basis, basisInverse) - .TransformBy(TrTransform.S(payload.exportUnitsFromAppUnits)) - .ToMatrix4x4(); - } - - /// Given a transform, returns that transform in another basis. - /// Since it's a Transform, xfInput is in Global (Room) space, Unity axes, decimeters. - /// The new basis is: Scene space, with the Payload's axes and units. - public static Matrix4x4 ChangeBasis( - Transform xfInput, SceneStatePayload payload) - { - Matrix4x4 basis = AxisConvention.GetFromUnity(payload.axes); - Matrix4x4 basisInverse = AxisConvention.GetToUnity(payload.axes); - return ChangeBasis(App.Scene.AsScene[xfInput], basis, basisInverse) - .TransformBy(TrTransform.S(payload.exportUnitsFromAppUnits)) - .ToMatrix4x4(); - } - - /// Returns a basis-change matrix that transforms from Unity axis conventions to - /// the conventions specified in the payload. - /// - /// Does *not* perform unit conversion, hence the name. - public static Matrix4x4 GetFromUnity_Axes(SceneStatePayload payload) - { - return AxisConvention.GetFromUnity(payload.axes); - } - - // -------------------------------------------------------------------------------------------- // - // Texture Collection Helper - // -------------------------------------------------------------------------------------------- // - - static public string GetTexturePath(Texture texture) - { -#if UNITY_EDITOR - // Copy the raw asset texture file and make sure it's either a PNG or JPG. - string texturePath = UnityEditor.AssetDatabase.GetAssetPath(texture); - texturePath = texturePath.Substring("Assets/".Length); - texturePath = Path.Combine(Application.dataPath, texturePath); - string extension = Path.GetExtension(texturePath).ToUpper(); - Debug.Assert(extension == ".PNG" || extension == ".JPG" || extension == ".JPEG", - String.Format("Texture {0} must be converted to png or jpg format", - texturePath)); - return texturePath; -#else - // Create an uncompressed texture from mainTex as a fallback when the asset database is - // not available. This only works on 2D textures that are readable. - string texFilename = Guid.NewGuid().ToString("D") + ".png"; - Texture2D texture2d = (Texture2D)texture; - Texture2D uncompressedTexture = new Texture2D( - texture.width, texture.height, TextureFormat.RGBA32, /*mipmap / mipChain:*/ false); - uncompressedTexture.SetPixels(texture2d.GetPixels()); - byte[] bytes = uncompressedTexture.EncodeToPNG(); - - // Save the texture file. - string texturePath = Path.Combine(Path.Combine(Path.GetDirectoryName(Application.dataPath), - ExportUtils.kProjectRelativeTextureExportRoot), - texFilename); - File.WriteAllBytes(texturePath, bytes); - return texturePath; -#endif - } - -#if UNITY_EDITOR && GAMEOBJ_EXPORT_TO_GLTF - public static SceneStatePayload GetSceneStateForGameObjectForExport( - GameObject gameObject, AxisConvention axes, Environment env) { - return ExportCollector.GetExportPayloadForGameObject(gameObject, axes, env); - } - - /// Returns a matrix: - /// - with units converted by the scale specified in the payload - /// - with basis changed by the axis convention in the payload - /// - with the scene transform subtracted out (so, converts from room to scene), but - /// only if the app is running. - /// This version also handles non-uniform scale (but stemming from what? the scene xf?) - public static Matrix4x4 ChangeBasisNonUniformScale(SceneStatePayload payload, Matrix4x4 root) { - Matrix4x4 basis = ExportUtils.GetBasisMatrix(payload); - - // Pre- and post-multiplying by the following matrix operations is the equivalent of - // .TransformBy(TrTransform.S(payload.exportUnitsFromAppUnits)). - Matrix4x4 xfScale = Matrix4x4.Scale(Vector3.one * payload.exportUnitsFromAppUnits); - Matrix4x4 xfScaleInverse = Matrix4x4.Scale(Vector3.one / payload.exportUnitsFromAppUnits); - - if (Application.isPlaying) { - // The world to scene matrix here performs the equivalent of App.Scene.AsScene[root] - // but works for non-uniform scale. - Matrix4x4 worldToSceneMatrix = App.Scene.transform.worldToLocalMatrix; - return xfScale * basis * worldToSceneMatrix * root * basis.inverse * xfScaleInverse; - } else { - return xfScale * basis * root * basis.inverse * xfScaleInverse; - } - } -#endif - - /// Returns a name based on originalName. - /// The name will be different from any names in usedNames, and will be added to usedNames. - public static string CreateUniqueName(string originalName, HashSet names) - { - if (string.IsNullOrEmpty(originalName)) - { - throw new ArgumentException("originalName"); - } - string baseName, ext; - { - // Don't use the Path functions because originalName may not be a valid path. - int dot = originalName.LastIndexOf('.'); - if (dot < 0) - { - baseName = originalName; - ext = ""; - } - else - { - baseName = originalName.Substring(0, dot); - ext = originalName.Substring(dot); - } - } - - for (int i = 0; ; ++i) - { - string subscript = (i == 0 ? "" : $"_{i}"); - string attempt = $"{baseName}{subscript}{ext}"; - if (names.Add(attempt)) - { - return attempt; - } - } - } - } -} // namespace TiltBrush +// Copyright 2020 The Tilt Brush Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// 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.Collections.Generic; +using System; +using System.IO; +using System.Linq; +using JetBrains.Annotations; +using UnityEngine; + +namespace TiltBrush +{ + + using TexcoordInfo = GeometryPool.TexcoordInfo; + using Semantic = GeometryPool.Semantic; + using StrokeGroup = SketchGroupTag; + + public static class ExportUtils + { + // Used to refer to built-in textures that we put in Support/ + public const string kBuiltInPrefix = "tiltbrush://"; + public const string kShaderDirectory = "shaders/brushes"; + public const string kProjectRelativeBrushExportRoot = "Support/TiltBrush.com/" + kShaderDirectory; + public const string kProjectRelativeEnvironmentExportRoot = "Support/TiltBrush.com/environments"; + public const string kProjectRelativeTextureExportRoot = "Support/TiltBrush.com/textures"; + public const string kProjectRelativeSupportBrushTexturesRoot = "Support/" + kShaderDirectory; + + // -------------------------------------------------------------------------------------------- // + // Brush/Canvas Export Payloads + // -------------------------------------------------------------------------------------------- // + + /// A canvas and some strokes + [UsedImplicitly(ImplicitUseTargetFlags.Members)] + public class ExportCanvas + { + public CanvasScript m_canvas; + private List m_strokes; + + public ExportCanvas(CanvasScript canvas, IEnumerable strokes) + { + m_canvas = canvas; + m_strokes = strokes.ToList(); + } + + public ExportCanvas(IGrouping group) + { + m_canvas = group.Key; + m_strokes = group.ToList(); + } + + public IEnumerable SplitByGroup() + { + return m_strokes.GroupBy(stroke => stroke.Group) + .Select(g => new ExportGroup(g)); + } + + public IEnumerable SplitByBrush() + { + return m_strokes.GroupBy(stroke => stroke.m_BrushGuid) + .Select(g => new ExportBrush(g)); + } + } + + /// A group id and some strokes + public class ExportGroup + { + public StrokeGroup m_group; + private List m_strokes; + + public ExportGroup(IGrouping group) + { + m_group = group.Key; + m_strokes = group.ToList(); + } + + public IEnumerable SplitByBrush() + { + return m_strokes.GroupBy(stroke => stroke.m_BrushGuid) + .Select(g => new ExportBrush(g)); + } + } + + /// A brush guid and some strokes + /// This is the only grouping that can be converted to geometry + public class ExportBrush + { + public BrushDescriptor m_desc; + private List m_strokes; + + public ExportBrush(IGrouping group) + { + m_desc = BrushCatalog.m_Instance.GetBrush(group.Key); + m_strokes = group.ToList(); + } + + public struct PoolAndStrokes + { + public GeometryPool pool; + public List strokes; + } + + // Returns a pool, or null if it's not from a pool. + private static GeometryPool GetPool(Stroke stroke) + { + if (stroke.m_BatchSubset == null) { return null; } + return stroke.m_BatchSubset.m_ParentBatch.Geometry; + } + + // Yields strokes in the same order as in the input, but adds an additional side effect: + // When the user consumes the stroke they will likely force its batch to become resident. + // This wrapper undoes that, preserving the state of the Batch's residency. + private IEnumerable + PreserveBatchResidency(IEnumerable input) + { + // We could do the "make it resident, make it not resident" dance on a stroke-by-stroke + // basis, but that would be ridiculously wasteful. Optimize by grouping adjacent strokes + // together if they share the same batch. + // + // When a sketch first loads, this optimization works extremely well because batches are + // contiguous in the stroke list. The more the user mutates (select, unselect, recolor) + // the less this will be true. There's not a lot we can do about it unless we want to + // sort the strokes by batch rather than by draw time (or whatever criteria the incoming + // iterator uses), which I think would be too invasive. + foreach (IGrouping group in + input.GroupBy(stroke => GetPool(stroke))) + { + GeometryPool pool = group.Key; + + // If we have to bring the pool into memory, save off enough data so we can + // push it back out. + Mesh previousBackingMesh = null; + if (pool != null && !pool.IsGeometryResident) + { + previousBackingMesh = pool.GetBackingMesh(); + // We currently only eject batch-owned GeometryPool to Mesh, so this is unlikely to trip; + // but we eventually may want to eject them to disk to save even more memory. + if (previousBackingMesh == null) + { + Debug.LogWarning("Not yet able to eject pool back to file; leaving it in memory"); + } + pool.EnsureGeometryResident(); + } + + foreach (Stroke stroke in group) + { + yield return stroke; + } + + if (previousBackingMesh != null) + { + pool.MakeGeometryNotResident(previousBackingMesh); + } + } + } + + // Puts the passed timestamp data into pool.texcoord2. + // It's assumed that the pool does not already have anything in texcoord2. + private static void AugmentWithTimestamps(GeometryPool pool, ref List timestamps) + { + if (App.UserConfig.Export.ExportStrokeTimestamp) + { + GeometryPool.VertexLayout withTxc2 = pool.Layout; + if (withTxc2.texcoord2.size == 0 && timestamps.Count == pool.NumVerts) + { + withTxc2.texcoord2 = new TexcoordInfo { size = 3, semantic = Semantic.Timestamp }; + pool.Layout = withTxc2; + pool.m_Texcoord2.v3 = timestamps; + timestamps = null; // don't let caller reuse the list + } + else + { + Debug.LogError("Internal error; cannot add timestamps"); + } + } + } + + // Appends timestamp data to the passed List. + // + // The timestamps are laid out like so: + // x = start of stroke + // y = end of stroke + // z = Roughly interpolated between the start and end of the stroke + // I say "roughly interpolated" because we make the assumption that each control point + // creates a fixed number of vertices. It's correct only to a first approximation. + private static void AppendTimestamps( + Stroke stroke, int numVerts, + List timestamps) + { + Vector3 ts = new Vector3(stroke.HeadTimestampMs * .001f, + stroke.TailTimestampMs * .001f, + 0); + foreach (float interpolated in MathUtils.LinearResampleCurve( + stroke.m_ControlPoints.Select(cp => cp.m_TimestampMs * .001f).ToArray(), + numVerts)) + { + ts.z = interpolated; + timestamps.Add(ts); + } + } + + /// Converts strokes to multiple GeometryPools whose size is <= vertexLimit. + /// The default vertexLimit is the maximum size allowed by Unity. + /// If a single stroke exceeds the vertex limit, the stroke will be ignored. + /// TODO: dangerous! vertexLimit should be a soft limit, with a hard limit of 65k + public IEnumerable ToGeometryBatches(int vertexLimit = 65534) + { + var layout = BrushCatalog.m_Instance.GetBrush(m_desc.m_Guid).VertexLayout; + var pool = new GeometryPool(); + var strokes = new List(); + // Timestamps are kept separate and only stitched in when we emit a Pool. + // This is because GeometryPool.Append() doesn't know what to do if the + // source and dest layouts are different. + List timestamps = new List(); + pool.Layout = layout; + foreach (var stroke in PreserveBatchResidency(m_strokes)) + { + while (true) + { + if (!stroke.IsGeometryEnabled) { continue; } + int oldNumVerts = pool.NumVerts; + if (pool.Append(stroke, vertexLimit)) + { + strokes.Add(stroke); + if (App.UserConfig.Export.ExportStrokeTimestamp) + { + AppendTimestamps(stroke, pool.NumVerts - oldNumVerts, timestamps); + } + // common case: it fits + break; + } + else if (pool.m_Vertices.Count > 0) + { + // it doesn't fit, but we can make a bit of forward progress by flushing the buffer + AugmentWithTimestamps(pool, ref timestamps); + yield return new PoolAndStrokes { pool = pool, strokes = strokes }; + pool = new GeometryPool(); + pool.Layout = layout; + strokes = new List(); + timestamps = new List(); + // loop around for another go + } + else + { + // very uncommon case: stroke won't fit even in an empty buffer. + // Should never happen with the default vertexLimit. + Debug.LogWarning("Cannot export stroke that exceeds vertex limit"); + // No choice but to ignore the stroke + break; + } + } + } + if (pool.m_Vertices.Count > 0) + { + AugmentWithTimestamps(pool, ref timestamps); + yield return new PoolAndStrokes { pool = pool, strokes = strokes }; + } + } + } + + // -------------------------------------------------------------------------------------------- // + // SceneState Export Payloads + // The state objects below are pure-state populated by the ExportCollector. + // -------------------------------------------------------------------------------------------- // + + // GetInstanceID() is not determinstic. + // The order in which objects are exported is somewhat determinstic. + // This class uses the order of export to determine the id. + public class DeterministicIdGenerator + { + private Dictionary m_instanceIdToId = new Dictionary(); + private int m_nextAvailable = 1; + public int GetIdFromInstanceId(UnityEngine.Object obj) + { + int instanceId = obj.GetInstanceID(); + if (m_instanceIdToId.ContainsKey(instanceId)) + { + return m_instanceIdToId[instanceId]; + } + else + { + var ret = m_nextAvailable; + m_nextAvailable += 1; + m_instanceIdToId[instanceId] = ret; + return ret; + } + } + } + /// The current exportable SceneState of Open Brush. + public class SceneStatePayload + { + // Metadata. + public string generator = "Tilt Brush 23.3.841faedfb compatible (Actually: Open Brush {0}.{1})"; + public DeterministicIdGenerator idGenerator = new DeterministicIdGenerator(); + + // Space Bases. + public readonly AxisConvention axes; + public readonly bool reverseWinding; + public readonly float exportUnitsFromAppUnits = App.UNITS_TO_METERS; + + // Entity Manifests. + public EnvPayload env = new EnvPayload(); + public LightsPayload lights = new LightsPayload(); + public List groups = new List(); + public GroupIdMapping groupIdMapping = new GroupIdMapping(); + // These actually contain the model/image data + public List modelMeshes = new List(); + public List imageQuads = new List(); + // These are bare nodes representing things that we currently can't export + public List referenceThings = new List(); + public readonly string temporaryDirectory = null; + + // If you pass a temporary directory, it may (or may not) be used + // for memory optimizations during the export. In this case, take + // care to call Destroy() if you want the payload to clean up after itself. + public SceneStatePayload(AxisConvention axes, string temporaryDirectory) + { + this.axes = axes; + this.temporaryDirectory = temporaryDirectory; + // The determinant can be used to detect if the basis-change has a mirroring. + // This matters because a mirroring turns the triangles inside-out, requiring + // us to flip their winding to preserve the surface orientation. + this.reverseWinding = (GetFromUnity_Axes(this).determinant < 0); + } + + // Tears down the payload as safely as possible; throws no exceptions + public void Destroy() + { + if (groups != null) + { + foreach (var item in groups) + { + item.Destroy(); + } + } + if (modelMeshes != null) + { + foreach (var item in modelMeshes) + { + item.Destroy(); + } + } + } + } + + // This should be deprecated in favor of putting a group id in all the payloads + public class GroupPayload + { + public UInt32 id; + public List brushMeshes = new List(); + public void Destroy() + { + if (brushMeshes != null) + { + foreach (var item in brushMeshes) + { + item.Destroy(); + } + } + } + } + + public class EnvPayload + { + public Guid guid; + public string description; + public Cubemap skyCubemap; + public bool useGradient; + public Color skyColorA; + public Color skyColorB; + public Vector3 skyGradientDir; + public Color fogColor; + public float fogDensity; + } + + public class LightPayload + { + public LightType type; + public string legacyUniqueName; // guaranteed unique but maybe not friendly + public string name; + public Color lightColor; + public Matrix4x4 xform; + } + + [UsedImplicitly(ImplicitUseTargetFlags.Members)] + public class LightsPayload + { + public Color ambientColor; // currently unused + public List lights = new List(); + } + + // Common to all MeshPayload. + // This is an _instance_ of a mesh, and corresponds to a GameObject/MeshRenderer + public abstract class BaseMeshPayload + { + // A unique not-very-human-readable string. + // "nodeName" and "geometryName" are _mostly_ unique except in edge cases like two distinct + // widgets having the same GetExportName(). + // Keeping this around also means I can diff vs old gltf1 files for testing purposes. + public string legacyUniqueName; + + // A pleasant-looking name for the node + public string nodeName; + public Matrix4x4 xform = Matrix4x4.identity; + // Not owned by this instance; ownership is potentially shared with other BaseMeshPayloads + public GeometryPool geometry; + // A pleasant-looking name for the geometry + public string geometryName; + public IExportableMaterial exportableMaterial; + + public readonly UInt32 group; + + protected BaseMeshPayload(uint groupId) { this.group = groupId; } + + /// Returns a string used to keep different models from having overlapping names. + /// Examples uses: + /// - Keep texture names from colliding + /// - Keep material names from colliding -- in particular this is an issue for + /// the name "defaultShadingGroup" which shows up in Poly-obj and Media Library-obj + /// imports a lot. + public abstract string MeshNamespace { get; } + + // Danger! This destroys resources shared by the entire SceneStatePayload. + // It is only public so it can be called during SceneStatePayload shutdown. + public void Destroy() + { + if (geometry != null) + { + geometry.Destroy(); + geometry = null; + } + } + } + + public class ImageQuadPayload : BaseMeshPayload + { + public override string MeshNamespace => "media"; + public ImageQuadPayload(uint groupId) : base(groupId) { } + } + + // MeshPayload for a poly or media library model; might also be used for + // exporting environments from the editor? + public class ModelMeshPayload : BaseMeshPayload + { + public Model model; + + // Enumerates the instances of a Model in the scene. + // Group by (model, modelId) to collect payloads from the same instance. + public int modelId; + + // These next two are base.xform in factored form: parentXform * localXform == base.xform + + // The transform of the parent ModelWidget. + // Payloads with the same model and modelId come from the same parent, + // therefore they have the same parentXform. + public Matrix4x4 parentXform; + + // This is slightly redundant because it's the same as instanceXform.inverse * base.xform. + // It's stored explicitly for slight added precision. + public Matrix4x4 localXform; + + public override string MeshNamespace + { + get + { + if (model.GetLocation().GetLocationType() == Model.Location.Type.IcosaAssetId) + { + return model.AssetId; // blows up if type is not PolyAssetId + } + else + { + string path = Path.GetFileNameWithoutExtension(model.RelativePath); + return System.Text.RegularExpressions.Regex.Replace( + path, @"[^a-zA-Z0-9_-]+", ""); + } + } + } + public ModelMeshPayload(uint groupId) : base(groupId) { } + } + + // MeshPayload for something drawn with a brush. + // Strokes are currently only used when exporting to USD + public class BrushMeshPayload : BaseMeshPayload + { + public List strokes; + public override string MeshNamespace => "brush"; + public BrushMeshPayload(uint groupId) : base(groupId) { } + } + + public class XformPayload + { + public readonly UInt32 group; + // This name isn't (currently) guaranteed to be unique among XformPayloads + public string name; + public Matrix4x4 xform; + + public XformPayload(uint groupId) { this.group = groupId; } + } + + // -------------------------------------------------------------------------------------------- // + // Data Collection Helpers + // -------------------------------------------------------------------------------------------- // + + /// Filters and returns geometry in a convenient format for export. + /// Returns geometry for the main canvas + public static ExportCanvas ExportMainCanvas() + { + // This is probably the more-useful one; it assumes we only have + // one interesting canvas (true, from a user perspective) and merges + // the selection canvas into its target canvas. + // + // It makes the assumption that the selection canvas is not playing + // fast-and-loose, and keeps its transform identical to its target + // canvas (ie, its transform is always identity). + // + // Of course, the selection canvas does play fast-and-loose, but + // we smack the canvas into place (via a deselect/reselect) before + // getting here. + var allowedBrushGuids = new HashSet( + BrushCatalog.m_Instance.AllBrushes + .Where(b => b.m_AllowExport) + .Select(b => (Guid)b.m_Guid)); + var main = App.Scene.MainCanvas; + var selection = App.Scene.SelectionCanvas; + var mainStrokes = SketchMemoryScript.AllStrokes() + .Where(stroke => allowedBrushGuids.Contains(stroke.m_BrushGuid) && + stroke.IsGeometryEnabled && + (stroke.Canvas == main || stroke.Canvas == selection)); + return new ExportCanvas(main, mainStrokes.ToList()); + } + + // Same as ExportAllCanvases but pretends all strokes are on the main canvas + // Does NOT transform strokes so ensure all canvases have identity transforms + public static ExportCanvas ExportAllCanvasesIgnoreLayers() + { + var allowedBrushGuids = new HashSet( + BrushCatalog.m_Instance.AllBrushes + .Where(b => b.m_AllowExport) + .Select(b => (Guid)b.m_Guid)); + var main = App.Scene.MainCanvas; + var selection = App.Scene.SelectionCanvas; + var mainStrokes = SketchMemoryScript + .AllStrokes() + .Where(stroke => allowedBrushGuids.Contains(stroke.m_BrushGuid) && stroke.IsGeometryEnabled); + return new ExportCanvas(main, mainStrokes.ToList()); + } + + /// Filters and returns geometry in a convenient format for export. + public static List ExportAllCanvases() + { + var allowedBrushGuids = new HashSet( + BrushCatalog.m_Instance.AllBrushes + .Where(b => b.m_AllowExport) + .Select(b => (Guid)b.m_Guid)); + + return SketchMemoryScript.AllStrokes() + .Where(stroke => allowedBrushGuids.Contains(stroke.m_BrushGuid) && + stroke.IsGeometryEnabled) + .GroupBy(stroke => stroke.Canvas) + .Select(canvasStrokes => new ExportCanvas(canvasStrokes)) + .ToList(); + } + + // -------------------------------------------------------------------------------------------- // + // Functional Conversion Helpers + // -------------------------------------------------------------------------------------------- // + + /// Applies change-of-basis conversions and distance conversions to a GeometryPool. + public static void ConvertUnitsAndChangeBasis(GeometryPool pool, SceneStatePayload payload) + { + ConvertScaleAndChangeBasis(pool, payload.exportUnitsFromAppUnits, GetFromUnity_Axes(payload)); + } + + private static void ConvertScaleAndChangeBasis( + GeometryPool pool, + float unitChange, + Matrix4x4 basisChange) + { + // If there's translation, it's ambiguous whether scale is applied before or after + // (probably the user means after, but still) + Debug.Assert((Vector3)basisChange.GetColumn(3) == Vector3.zero); + Matrix4x4 basisAndUnitChange = Matrix4x4.Scale(unitChange * Vector3.one) * basisChange; + +#if false // this code is pendantic but is useful to describe what's _really_ going on here + // xfBivector is the transform to use for normals, tangents, and other cross-products. + // Extracting rotation from a mat4 is hard, so take advantage of the fact that basisChange + // is a (maybe improper) rotation, an improper rotation being a rotation with scale -1. + // Matrix4x4 xfBivector = ExtractRotation(basisAndUnitChange); + Matrix4x4 xfBivector = basisChange; + if (basisChange.determinant < 0) { + // remove the -1 uniform scale by giving it yet more -1 uniform scale. + xfBivector = Matrix4x4.Scale(-Vector3.one) * xfBivector; + } + + // The exporter flips triangle winding when handedness flips, but it leaves the job unfinished; + // it needs to also flip the normals and tangents, since they're calculated from cross products. + // Detect that and kludge in an extra -1 scale to finish the job. + if (basisChange.determinant < 0) { + xfBivector = Matrix4x4.Scale(-Vector3.one) * xfBivector; + } +#else + Matrix4x4 xfBivector = basisChange; // The mirroring and the winding-flip cancel each other out +#endif + pool.ApplyTransform(basisAndUnitChange, xfBivector, unitChange, 0, pool.NumVerts); + } + + /// Convert the vertex colors to linear + public static List ConvertToLinearColorspace(List srgb) + { + return new List(srgb.Select(c32 => ((Color)c32).linear)); + } + + public static void ConvertToSrgbColorspace(Color[] linear) + { + for (int i = 0; i < linear.Length; i++) + { + linear[i] = linear[i].gamma; + } + } + + // Unused and untested +#if false + /// Convert the vertex Color32s to linear + /// Beware that you will lose information when quantizing down from + /// linear-float32 to linear-uint8. + public static void ConvertToLinearColorspace(MeshPayload meshes) { + for (int i = 0; i < meshes.Count; i++) { + var pool = meshes.geometry[i]; + for (int j = 0; j < pool.m_Colors.Count; j++) { + pool.m_Colors[j] = ((Color)pool.m_Colors[j]).linear; + } + } + } + /// Convert the light colors to linear + /// Beware that you will lose information when quantizing down from + /// linear-float32 to linear-uint8. + public static void ConvertToLinearColorspace(LightPayload lights) { + // XXX: these values can be > 1 because they are pre-multiplied by intensity + // Is it more appropriate to convert the base color from sRGB -> Linear, + // _then_ multiply by intensity? + lights.ambientColor = lights.ambientColor.linear; + for (int i = 0; i < lights.Count; i++) { + lights.lightColor[i] = lights.lightColor[i].linear; + } + } + /// Convert the environment (sky/fog) colors to linear + public static void ConvertToLinearColorspace(EnvPayload env) { + env.fogColor = env.fogColor.linear; + env.skyColorA = env.skyColorA.linear; + env.skyColorB = env.skyColorB.linear; + } +#endif + + + /// Flips winding order by swapping indices indexA and indexB. + /// indexA and indexB must be in the range [0, 2] and not equal to each other. + public static void ReverseTriangleWinding(GeometryPool pool, int indexA, int indexB) + { + if (indexA == indexB || indexA < 0 || indexA > 2) + { + throw new ArgumentException("indexA"); + } + if (indexB < 0 || indexB > 2) + { + throw new ArgumentException("indexB"); + } + var tris = pool.m_Tris; + int count = tris.Count; + for (int i = 0; i < count; i += 3) + { + var tmp = tris[i + indexA]; + tris[i + indexA] = tris[i + indexB]; + tris[i + indexB] = tmp; + } + } + + /// Given a transform, returns that transform in another basis. + /// The new basis is specified by outputFromInput. + public static Matrix4x4 ChangeBasis( + Matrix4x4 xfInput, + Matrix4x4 outputFromInput, Matrix4x4 inputFromOutput) + { + return outputFromInput * xfInput * inputFromOutput; + } + + /// Given a transform, returns that transform in another basis. + /// The new basis is specified by outputFromInput. + /// + /// Not guaranteed to work if the change-of-basis matrix has non-uniform + /// scale. Otherwise, the resulting transform will not "fit" in a TrTransform. + public static TrTransform ChangeBasis( + TrTransform xfInput, + Matrix4x4 outputFromInput, Matrix4x4 inputFromOutput) + { + // It might make this a little more accurate if outputFromInput were a TrTransform. + // Although... outputFromInput and inputFromOutput expressed as Matrix4x4 are always + // infinitely precise, for axis convention changes at least. Doing the same with a quat + // might involve sqrt(2)s. But maybe not for the common case of unity -> fbx / gltf? + Matrix4x4 m = outputFromInput * xfInput.ToMatrix4x4() * inputFromOutput; + return TrTransform.FromMatrix4x4(m); + } + + /// Given a transform, returns that transform in another basis. + /// The new basis is specified by outputFromInput. + /// + /// Not guaranteed to work if the change-of-basis matrix has non-axis-aligned + /// scale, or if the rotation portion can't be expressed as the product of 90 degree + /// rotations about an axis. Otherwise, the resulting scale will not "fit" in a Vec3. + public static void ChangeBasis( + Vector3 inputTranslation, Quaternion inputRotation, Vector3 inputScale, + out Vector3 translation, out Quaternion rotation, out Vector3 scale, + Matrix4x4 outputFromInput, Matrix4x4 inputFromOutput) + { + TrTransform output = ChangeBasis( + TrTransform.TR(inputTranslation, inputRotation), + outputFromInput, inputFromOutput); + translation = output.translation; + rotation = output.rotation; + // Scale is a bit trickier. + Matrix4x4 m = outputFromInput * Matrix4x4.Scale(inputScale) * inputFromOutput; + scale = new Vector3(m[0, 0], m[1, 1], m[2, 2]); + m[0, 0] = m[1, 1] = m[2, 2] = 1; + Debug.Assert(m.isIdentity); + } + + /// Given a TrTransform, returns that transform as a mat4 in another basis. + /// The new basis is specified by the payload. + /// This changes both axes and units. + public static Matrix4x4 ChangeBasis( + TrTransform xfInput, SceneStatePayload payload) + { + Matrix4x4 basis = AxisConvention.GetFromUnity(payload.axes); + Matrix4x4 basisInverse = AxisConvention.GetToUnity(payload.axes); + return ChangeBasis(xfInput, basis, basisInverse) + .TransformBy(TrTransform.S(payload.exportUnitsFromAppUnits)) + .ToMatrix4x4(); + } + + /// Given a transform, returns that transform in another basis. + /// Since it's a Transform, xfInput is in Global (Room) space, Unity axes, decimeters. + /// The new basis is: Scene space, with the Payload's axes and units. + public static Matrix4x4 ChangeBasis( + Transform xfInput, SceneStatePayload payload) + { + Matrix4x4 basis = AxisConvention.GetFromUnity(payload.axes); + Matrix4x4 basisInverse = AxisConvention.GetToUnity(payload.axes); + return ChangeBasis(App.Scene.AsScene[xfInput], basis, basisInverse) + .TransformBy(TrTransform.S(payload.exportUnitsFromAppUnits)) + .ToMatrix4x4(); + } + + /// Returns a basis-change matrix that transforms from Unity axis conventions to + /// the conventions specified in the payload. + /// + /// Does *not* perform unit conversion, hence the name. + public static Matrix4x4 GetFromUnity_Axes(SceneStatePayload payload) + { + return AxisConvention.GetFromUnity(payload.axes); + } + + // -------------------------------------------------------------------------------------------- // + // Texture Collection Helper + // -------------------------------------------------------------------------------------------- // + + static public string GetTexturePath(Texture texture) + { +#if UNITY_EDITOR + // Copy the raw asset texture file and make sure it's either a PNG or JPG. + string texturePath = UnityEditor.AssetDatabase.GetAssetPath(texture); + texturePath = texturePath.Substring("Assets/".Length); + texturePath = Path.Combine(Application.dataPath, texturePath); + string extension = Path.GetExtension(texturePath).ToUpper(); + Debug.Assert(extension == ".PNG" || extension == ".JPG" || extension == ".JPEG", + String.Format("Texture {0} must be converted to png or jpg format", + texturePath)); + return texturePath; +#else + // Create an uncompressed texture from mainTex as a fallback when the asset database is + // not available. This only works on 2D textures that are readable. + string texFilename = Guid.NewGuid().ToString("D") + ".png"; + Texture2D texture2d = (Texture2D)texture; + Texture2D uncompressedTexture = new Texture2D( + texture.width, texture.height, TextureFormat.RGBA32, /*mipmap / mipChain:*/ false); + uncompressedTexture.SetPixels(texture2d.GetPixels()); + byte[] bytes = uncompressedTexture.EncodeToPNG(); + + // Save the texture file. + string texturePath = Path.Combine(Path.Combine(Path.GetDirectoryName(Application.dataPath), + ExportUtils.kProjectRelativeTextureExportRoot), + texFilename); + File.WriteAllBytes(texturePath, bytes); + return texturePath; +#endif + } + +#if UNITY_EDITOR && GAMEOBJ_EXPORT_TO_GLTF + public static SceneStatePayload GetSceneStateForGameObjectForExport( + GameObject gameObject, AxisConvention axes, Environment env) { + return ExportCollector.GetExportPayloadForGameObject(gameObject, axes, env); + } + + /// Returns a matrix: + /// - with units converted by the scale specified in the payload + /// - with basis changed by the axis convention in the payload + /// - with the scene transform subtracted out (so, converts from room to scene), but + /// only if the app is running. + /// This version also handles non-uniform scale (but stemming from what? the scene xf?) + public static Matrix4x4 ChangeBasisNonUniformScale(SceneStatePayload payload, Matrix4x4 root) { + Matrix4x4 basis = ExportUtils.GetBasisMatrix(payload); + + // Pre- and post-multiplying by the following matrix operations is the equivalent of + // .TransformBy(TrTransform.S(payload.exportUnitsFromAppUnits)). + Matrix4x4 xfScale = Matrix4x4.Scale(Vector3.one * payload.exportUnitsFromAppUnits); + Matrix4x4 xfScaleInverse = Matrix4x4.Scale(Vector3.one / payload.exportUnitsFromAppUnits); + + if (Application.isPlaying) { + // The world to scene matrix here performs the equivalent of App.Scene.AsScene[root] + // but works for non-uniform scale. + Matrix4x4 worldToSceneMatrix = App.Scene.transform.worldToLocalMatrix; + return xfScale * basis * worldToSceneMatrix * root * basis.inverse * xfScaleInverse; + } else { + return xfScale * basis * root * basis.inverse * xfScaleInverse; + } + } +#endif + + /// Returns a name based on originalName. + /// The name will be different from any names in usedNames, and will be added to usedNames. + public static string CreateUniqueName(string originalName, HashSet names) + { + if (string.IsNullOrEmpty(originalName)) + { + throw new ArgumentException("originalName"); + } + string baseName, ext; + { + // Don't use the Path functions because originalName may not be a valid path. + int dot = originalName.LastIndexOf('.'); + if (dot < 0) + { + baseName = originalName; + ext = ""; + } + else + { + baseName = originalName.Substring(0, dot); + ext = originalName.Substring(dot); + } + } + + for (int i = 0; ; ++i) + { + string subscript = (i == 0 ? "" : $"_{i}"); + string attempt = $"{baseName}{subscript}{ext}"; + if (names.Add(attempt)) + { + return attempt; + } + } + } + } +} // namespace TiltBrush diff --git a/Assets/Scripts/Export/GltfExportStandinManager.cs b/Assets/Scripts/Export/GltfExportStandinManager.cs new file mode 100644 index 0000000000..0703a64491 --- /dev/null +++ b/Assets/Scripts/Export/GltfExportStandinManager.cs @@ -0,0 +1,47 @@ +// Copyright 2024 The Open Brush Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// 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.Linq; +using UnityEngine; +using UnityEngine.Serialization; + +namespace TiltBrush +{ + public class GltfExportStandinManager : MonoBehaviour + { + [SerializeField] public Transform m_TemporarySkySphere; + [NonSerialized] public static GltfExportStandinManager m_Instance; + private List m_TemporaryCameras; + + void Awake() + { + m_Instance = this; + } + + public void CreateSkyStandin() + { + // TODO check if we need box vs sphere etc + m_TemporarySkySphere.GetComponent().material = RenderSettings.skybox; + m_TemporarySkySphere.gameObject.SetActive(false); + } + + public void DestroySkyStandin() + { + m_TemporarySkySphere.gameObject.SetActive(false); + } + } +} + diff --git a/Assets/Scripts/Export/GltfExportStandinManager.cs.meta b/Assets/Scripts/Export/GltfExportStandinManager.cs.meta new file mode 100644 index 0000000000..46c28027a4 --- /dev/null +++ b/Assets/Scripts/Export/GltfExportStandinManager.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 14919aff2e114a19b65a5e58509e1d81 +timeCreated: 1718461146 \ No newline at end of file diff --git a/Assets/Scripts/Export/OpenBrushExportPlugin.cs b/Assets/Scripts/Export/OpenBrushExportPlugin.cs index cc670471bd..ed8b857e94 100644 --- a/Assets/Scripts/Export/OpenBrushExportPlugin.cs +++ b/Assets/Scripts/Export/OpenBrushExportPlugin.cs @@ -25,17 +25,88 @@ public override GLTFExportPluginContext CreateInstance(ExportContext context) public class OpenBrushExportPluginConfig : GLTFExportPluginContext { private Dictionary _meshesToBatches; - - private List _ignoreList = new() - { - "SnapGrid3D", - "Preview Light" - }; + private List m_CameraPathsCameras; public override void BeforeSceneExport(GLTFSceneExporter exporter, GLTFRoot gltfRoot) { - SelectionManager.m_Instance.ClearActiveSelection(); + if (Application.isPlaying && App.UserConfig.Export.ExportCustomSkybox) + { + GltfExportStandinManager.m_Instance.CreateSkyStandin(); + } + SelectionManager.m_Instance?.ClearActiveSelection(); _meshesToBatches = new Dictionary(); + GenerateCameraPathsCameras(); + } + + private void GenerateCameraPathsCameras() + { + if (!Application.isPlaying) return; + m_CameraPathsCameras = new List(); + var cameraPathWidgets = WidgetManager.m_Instance.CameraPathWidgets.ToArray(); + for (var i = 0; i < cameraPathWidgets.Length; i++) + { + var widget = cameraPathWidgets[i]; + var layer = widget.m_WidgetScript.Canvas; + var go = GameObject.Instantiate(new GameObject(), layer.transform); + go.name = $"CameraPath_{i}_{widget.m_WidgetScript.name}"; + var cam = go.AddComponent(); + m_CameraPathsCameras.Add(cam); + } + } + + private void ExportCameraPaths(GLTFSceneExporter exporter) + { + var cameraPathWidgets = WidgetManager.m_Instance.CameraPathWidgets.ToArray(); + for (var i = 0; i < cameraPathWidgets.Length; i++) + { + var cam = m_CameraPathsCameras[i]; + var widget = cameraPathWidgets[i]; + + GLTFAnimation anim = new GLTFAnimation(); + anim.Name = cam.gameObject.name; + + var posKnots = widget.WidgetScript.Path.PositionKnots; + var posTimes = new float[posKnots.Count]; + var posValues = new object[posKnots.Count]; + for (var j = 0; j < posKnots.Count; j++) + { + var knot = posKnots[j]; + var xf = knot.KnotXf; + var t = knot.PathT.T; + posTimes[j] = t; + posValues[j] = xf.position; + } + exporter.AddAnimationData(cam.gameObject, "translation", anim, posTimes, posValues); + + var rotKnots = widget.WidgetScript.Path.RotationKnots; + var rotTimes = new float[rotKnots.Count]; + var rotValues = new object[rotKnots.Count]; + for (var j = 0; j < rotKnots.Count; j++) + { + var knot = rotKnots[j]; + var xf = knot.KnotXf; + var t = knot.PathT.T; + posTimes[j] = t; + posValues[j] = xf.rotation; + } + exporter.AddAnimationData(cam.gameObject, "rotation", anim, posTimes, posValues); + + var fovKnots = widget.WidgetScript.Path.FovKnots; + var fovTimes = new float[fovKnots.Count]; + var fovValues = new object[fovKnots.Count]; + for (var j = 0; j < fovKnots.Count; j++) + { + var knot = fovKnots[j]; + var xf = knot.KnotXf; + var t = knot.PathT.T; + posTimes[j] = t; + posValues[j] = xf.rotation; + } + exporter.AddAnimationData(cam, "field of view", anim, fovTimes, fovValues); + + exporter.GetRoot().Animations.Add(anim); + GameObject.Destroy(cam); + } } private Transform GetOrCreateGroupTransform(CanvasScript layer, int group) @@ -70,18 +141,6 @@ private Transform GetOrCreateGroupTransform(CanvasScript layer, int group) public void BeforeLayerExport(Transform transform) { var canvas = transform.GetComponent(); - foreach (Transform child in transform) - { - if (_ignoreList.Contains(child.name)) - { - child.tag = "EditorOnly"; - } - - if (child.GetComponent() != null) - { - child.tag = "EditorOnly"; - } - } if (App.UserConfig.Export.KeepStrokes) { @@ -115,14 +174,28 @@ public void BeforeLayerExport(Transform transform) } } + public override bool ShouldNodeExport(GLTFSceneExporter exporter, GLTFRoot gltfRoot, Transform transform) + { + Type[] excludedTypes = + { + typeof(SnapGrid3D), + typeof(StencilWidget), + typeof(CameraPathWidget) + }; + bool hasExcludedComponent = excludedTypes.Any(t => transform.GetComponent(t) != null); + bool excludedName = false; // TODO + return !hasExcludedComponent && !excludedName; + } + public override void BeforeNodeExport(GLTFSceneExporter exporter, GLTFRoot gltfRoot, Transform transform, Node node) { if (transform.GetComponent() != null) { BeforeLayerExport(transform); } - - if (!App.UserConfig.Export.KeepStrokes && App.UserConfig.Export.ExportStrokeMetadata) + if (!Application.isPlaying) return; + if (!App.UserConfig.Export.KeepStrokes && + App.UserConfig.Export.ExportStrokeMetadata) { // We'll need a way to find the batch for each mesh later var batch = transform.GetComponent(); @@ -177,6 +250,7 @@ public override void AfterNodeExport(GLTFSceneExporter exporter, GLTFRoot gltfRo AfterLayerExport(transform); } + if (!Application.isPlaying) return; if (App.UserConfig.Export.KeepStrokes && App.UserConfig.Export.ExportStrokeMetadata) { var brush = transform.GetComponent(); @@ -226,6 +300,7 @@ public override void AfterNodeExport(GLTFSceneExporter exporter, GLTFRoot gltfRo public override void AfterPrimitiveExport(GLTFSceneExporter exporter, Mesh mesh, MeshPrimitive primitive, int index) { + if (!Application.isPlaying) return; if (App.UserConfig.Export.ExportStrokeMetadata) { if (App.UserConfig.Export.KeepStrokes) @@ -269,21 +344,82 @@ public override void AfterMaterialExport(GLTFSceneExporter exporter, GLTFRoot gl // Only handle brush materials if (!material.shader.name.StartsWith("Brush/")) return; - // Strip the (Instance) suffix from the material node name - materialNode.Name = materialNode.Name.Replace("(Instance)", "").Trim(); - materialNode.Name = $"ob-{materialNode.Name}"; + // TODO - This assumes that every brush has a unique material with a unique name + // Currently, this is true, but it may not always be the case + var brushes = BrushCatalog.m_Instance.AllBrushes + .Where(b => b.Material.name == material.name) + .ToList(); - var brush = BrushCatalog.m_Instance.AllBrushes.FirstOrDefault(b => b.DurableName == materialNode.Name); + switch (brushes.Count) + { + case 0: + Debug.LogError($"No matching brush found for material {material.name}"); + return; + case > 1: + Debug.LogError($"Multiple brushes with the same material name: {material.name}"); + return; + } + + var brush = brushes[0]; + var manifest = BrushCatalog.m_Instance.GetBrush(brush.m_Guid); - if (brush != null && brush.BlendMode == ExportableMaterialBlendMode.AdditiveBlend) + materialNode.Name = $"ob-{manifest.DurableName}"; + // Do we need to override the regular UnityGLTF logic here? + materialNode.DoubleSided = manifest.m_RenderBackfaces; + + switch (manifest.m_BlendMode) { - AddExtension(materialNode, EXT_blend_operations.Add); + case ExportableMaterialBlendMode.AdditiveBlend: + AddExtension(materialNode, EXT_blend_operations.Add); + materialNode.AlphaMode = AlphaMode.BLEND; + break; + case ExportableMaterialBlendMode.AlphaMask: + materialNode.AlphaMode = AlphaMode.MASK; + break; + case ExportableMaterialBlendMode.AlphaBlend: + materialNode.AlphaMode = AlphaMode.BLEND; + break; } } public override void AfterSceneExport(GLTFSceneExporter exporter, GLTFRoot gltfRoot) { + if (!Application.isPlaying) return; + + ExportCameraPaths(exporter); + if (App.UserConfig.Export.ExportCustomSkybox) + { + GltfExportStandinManager.m_Instance.DestroySkyStandin(); + } + gltfRoot.Asset.Generator = $"Open Brush UnityGLTF Exporter {App.Config.m_VersionNumber}.{App.Config.m_BuildStamp})"; + + JToken ColorToJArray(Color c) => JToken.FromObject(new { c.r, c.g, c.b, c.a }); + JToken Vector3ToJArray(Vector3 c) => JToken.FromObject(new { c.x, c.y, c.z }); + + var metadata = new SketchSnapshot().GetSketchMetadata(); + + var settings = SceneSettings.m_Instance; + Environment env = settings.GetDesiredPreset(); + var extras = new JObject(); + + var pose = metadata.SceneTransformInRoomSpace; + extras["TB_EnvironmentGuid"] = env.m_Guid.ToString("D"); + extras["TB_Environment"] = env.Description; + extras["TB_UseGradient"] = settings.InGradient ? "true" : "false"; + extras["TB_SkyColorA"] = ColorToJArray(settings.SkyColorA); + extras["TB_SkyColorB"] = ColorToJArray(settings.SkyColorB); + Matrix4x4 exportFromUnity = AxisConvention.GetFromUnity(AxisConvention.kGltf2); + extras["TB_SkyGradientDirection"] = Vector3ToJArray( + exportFromUnity * (settings.GradientOrientation * Vector3.up)); + extras["TB_FogColor"] = ColorToJArray(settings.FogColor); + extras["TB_FogDensity"] = settings.FogDensity; + extras["TB_PoseTranslation"] = Vector3ToJArray(pose.translation); + extras["TB_PoseRotation"] = Vector3ToJArray(pose.rotation.eulerAngles); + extras["TB_PoseScale"] = pose.scale; + // Experimental + // extras["TB_metadata"] = JObject.FromObject(metadata); + gltfRoot.Extras = extras; } private static void SafeDestroy(Object o) diff --git a/Assets/Scripts/Export/TiltBrushUriLoader.cs b/Assets/Scripts/Export/TiltBrushUriLoader.cs index 438e7f8ba7..163ceea01d 100644 --- a/Assets/Scripts/Export/TiltBrushUriLoader.cs +++ b/Assets/Scripts/Export/TiltBrushUriLoader.cs @@ -1,69 +1,69 @@ -// Copyright 2020 The Tilt Brush Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// 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.IO; -using TiltBrushToolkit; -using UnityEngine; -using ToolkitRawImage = TiltBrushToolkit.RawImage; - -namespace TiltBrush -{ - - public class TiltBrushUriLoader : IUriLoader - { - private string m_uriBase; - private IUriLoader m_delegate; - private bool m_loadImages; - - /// If loadImages=true, use a C# image loader which doesn't need to be run on - /// the main thread (helps avoid hitching) but is much slower than Texture2D.LoadImageData. - public TiltBrushUriLoader(string glbPath, string uriBase, bool loadImages) - { - m_loadImages = loadImages; - m_uriBase = uriBase; - m_delegate = new BufferedStreamLoader(glbPath, uriBase); - } - - public IBufferReader Load(string uri) - { - // null uri means the binary chunk of a .glb - uri = (uri == null) ? null : PolyRawAsset.GetPolySanitizedFilePath(uri); - return m_delegate.Load(uri); - } - - public bool CanLoadImages() { return m_loadImages; } - - public ToolkitRawImage LoadAsImage(string uri) - { - uri = PolyRawAsset.GetPolySanitizedFilePath(uri); - string path = Path.Combine(m_uriBase, uri); - RawImage rawImage = ImageUtils.FromImageData(File.ReadAllBytes(path), path); - return new ToolkitRawImage - { - format = TextureFormat.RGBA32, - colorData = rawImage.ColorData, - colorWidth = rawImage.ColorWidth, - colorHeight = rawImage.ColorHeight - }; - } - -#if UNITY_EDITOR - public UnityEngine.Texture2D LoadAsAsset(string uri) - { - return m_delegate.LoadAsAsset(uri); - } -#endif - } - -} // namespace TiltBrush +// Copyright 2020 The Tilt Brush Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// 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.IO; +using TiltBrushToolkit; +using UnityEngine; +using ToolkitRawImage = TiltBrushToolkit.RawImage; + +namespace TiltBrush +{ + + public class TiltBrushUriLoader : IUriLoader + { + private string m_uriBase; + private IUriLoader m_delegate; + private bool m_loadImages; + + /// If loadImages=true, use a C# image loader which doesn't need to be run on + /// the main thread (helps avoid hitching) but is much slower than Texture2D.LoadImageData. + public TiltBrushUriLoader(string glbPath, string uriBase, bool loadImages) + { + m_loadImages = loadImages; + m_uriBase = uriBase; + m_delegate = new BufferedStreamLoader(glbPath, uriBase); + } + + public IBufferReader Load(string uri) + { + // null uri means the binary chunk of a .glb + uri = (uri == null) ? null : IcosaRawAsset.GetPolySanitizedFilePath(uri); + return m_delegate.Load(uri); + } + + public bool CanLoadImages() { return m_loadImages; } + + public ToolkitRawImage LoadAsImage(string uri) + { + uri = IcosaRawAsset.GetPolySanitizedFilePath(uri); + string path = Path.Combine(m_uriBase, uri); + RawImage rawImage = ImageUtils.FromImageData(File.ReadAllBytes(path), path); + return new ToolkitRawImage + { + format = TextureFormat.RGBA32, + colorData = rawImage.ColorData, + colorWidth = rawImage.ColorWidth, + colorHeight = rawImage.ColorHeight + }; + } + +#if UNITY_EDITOR + public UnityEngine.Texture2D LoadAsAsset(string uri) + { + return m_delegate.LoadAsAsset(uri); + } +#endif + } + +} // namespace TiltBrush diff --git a/Assets/Scripts/GUI/AdminPanel.cs b/Assets/Scripts/GUI/AdminPanel.cs index d46b99c9c0..be6b251156 100644 --- a/Assets/Scripts/GUI/AdminPanel.cs +++ b/Assets/Scripts/GUI/AdminPanel.cs @@ -59,7 +59,9 @@ public class AdminPanel : BasePanel void UpdateShareButtonText() { // Skip redundant updates - bool currentLoggedIn = App.GoogleIdentity.LoggedIn || App.SketchfabIdentity.LoggedIn; + bool currentLoggedIn = App.GoogleIdentity.LoggedIn + || App.SketchfabIdentity.LoggedIn + || App.IcosaIsLoggedIn; if (currentLoggedIn == m_UpdateShareButtonState) { return; } m_UpdateShareButtonState = currentLoggedIn; diff --git a/Assets/Scripts/GUI/BasePanel.cs b/Assets/Scripts/GUI/BasePanel.cs index 5868bc41c7..7be7b1a4c1 100644 --- a/Assets/Scripts/GUI/BasePanel.cs +++ b/Assets/Scripts/GUI/BasePanel.cs @@ -1,1687 +1,1687 @@ -// Copyright 2020 The Tilt Brush Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// 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 UnityEngine; -using UnityEngine.Localization; -using UnityEngine.Localization.Settings; -using TMPro; - -namespace TiltBrush -{ - - [System.Serializable] - public struct PopupMapKey - { - public GameObject m_PopUpPrefab; - public SketchControlsScript.GlobalCommands m_Command; - } - - public class BasePanel : MonoBehaviour - { - static private float GAZE_DISTANCE = 10 * App.METERS_TO_UNITS; - static private float LARGE_DISTANCE = 9999.0f * App.METERS_TO_UNITS; - - // Types etc - - protected class TextSpring - { - public float m_CurrentAngle; - public float m_DesiredAngle; - public float m_Velocity; - - public void Update(float fK, float fDampen) - { - float fToDesired = m_DesiredAngle - m_CurrentAngle; - fToDesired *= fK; - float fDampenedVel = m_Velocity * fDampen; - float fSpringForce = fToDesired - fDampenedVel; - m_Velocity += fSpringForce; - m_CurrentAngle += (m_Velocity * Time.deltaTime); - } - } - - protected enum DescriptionState - { - Open, - Closing, - Closed - } - - protected enum PanelState - { - Unused, - Unavailable, - Available, - } - - // These names are used in our player prefs, so they must be protected from obfuscation - // Do not change the names of any of them, unless they've never been released. - [Serializable] - public enum PanelType - { - SketchSurface, - Color, - Brush, - AudioReactor, - AdminPanelMobile, - ToolsBasicMobile, - ToolsBasic, - Experimental, - ToolsAdvancedMobile, - MemoryWarning, - Labs, - Sketchbook, - SketchbookMobile, - BrushMobile, - AppSettings, - Tutorials, - Reference, - Lights, - GuideTools, - Environment, - Camera, - Testing, - Poly, - BrushExperimental, - ToolsAdvanced, - AppSettingsMobile, - AdminPanel, - ExtraPanel, - ExtraMobile, - PolyMobile, - LabsMobile, - ReferenceMobile, - CameraPath, - BrushLab, - WebcamPanel = 5200, - Scripts = 6000, - SnapSettings = 8000, - StencilSettings = 20200, - LayersPanel = 15000, - TransformPanel = 12000, - } - - private enum FixedTransitionState - { - Floating, - FixedToFloating, - FloatingToFixed, - Fixed - } - - // Inspector data, tunables - [SerializeField] protected PanelType m_PanelType; - - [SerializeField] protected Collider m_Collider; - [SerializeField] public GameObject m_Mesh; - [SerializeField] protected Renderer m_Border; - [SerializeField] protected Collider m_MeshCollider; - [SerializeField] protected Vector3 m_ParticleBounds; - - [SerializeField] protected PopupMapKey[] m_PanelPopUpMap; - [SerializeField] protected string m_PanelDescription; - [SerializeField] protected LocalizedString m_LocalizedPanelDescription; - - public string PanelDescription - { - get - { - try - { - var locString = m_LocalizedPanelDescription.GetLocalizedStringAsync().Result; - return locString; - } - catch - { - return m_PanelDescription; - } - } - } - - [SerializeField] protected GameObject m_PanelDescriptionPrefab; - - [SerializeField] protected Vector3 m_PanelDescriptionOffset; - [SerializeField] protected Color m_PanelDescriptionColor; - - [SerializeField] protected GameObject m_PanelFlairPrefab; - [SerializeField] protected Vector3 m_PanelFlairOffset; - - [SerializeField] protected float m_DescriptionSpringK = 4.0f; - [SerializeField] protected float m_DescriptionSpringDampen = 0.2f; - [SerializeField] protected float m_DescriptionClosedAngle = -90.0f; - [SerializeField] protected float m_DescriptionOpenAngle = 0.0f; - [SerializeField] protected float m_DescriptionAlphaDistance = 90.0f; - - [SerializeField] protected GameObject[] m_Decor; - - [SerializeField] protected float m_GazeHighlightScaleMultiplier = 1.2f; - - [SerializeField] private float m_BorderMeshWidth = 0.02f; - [SerializeField] private float m_BorderMeshAdvWidth = 0.01f; - - [SerializeField] public float m_PanelSensitivity = 0.1f; - [SerializeField] protected bool m_ClampToBounds = false; - [SerializeField] protected Vector3 m_ReticleBounds; - - [SerializeField] public float m_BorderSphereHighlightRadius; - [SerializeField] protected Vector2 m_PositioningSpheresBounds; - [SerializeField] protected float m_PositioningSphereRadius = 0.4f; - - [SerializeField] public bool m_UseGazeRotation = false; - [SerializeField] public float m_MaxGazeRotation = 20.0f; - [SerializeField] protected float m_GazeActivateSpeed = 8.0f; - - [SerializeField] public Vector3 m_InitialSpawnPos; - [SerializeField] public Vector3 m_InitialSpawnRotEulers; - - [SerializeField] public float m_WandAttachAngle; - [SerializeField] public float m_WandAttachYOffset; - [SerializeField] public float m_WandAttachHalfHeight; - [SerializeField] private bool m_BeginFixed; - [SerializeField] private bool m_CanBeFixedToWand = true; - [SerializeField] private bool m_CanBeDetachedFromWand = true; - - [SerializeField] private float m_PopUpGazeDuration = .2f; - - [SerializeField] protected MeshRenderer[] m_PromoBorders; - - protected const float m_SwipeThreshold = 0.4f; - protected Material m_BorderMaterial; - - // Public, mutable data - - [NonSerialized] public float m_SweetSpotDistance = 1.0f; - [NonSerialized] public bool m_Fixed; - [NonSerialized] public bool m_WandPrimedForAttach; - [NonSerialized] public float m_WandAttachRadiusAdjust; - [NonSerialized] public float m_WandAttachYOffset_Target; - // This is used to store the Y offset of a fixed panel at the point where the user begins - // interacting with a panelWidget. Storing this value allows modifications to the panes to be - // undone. When the user ends interaction, _Stable is updated to be the _Target. - [NonSerialized] public float m_WandAttachYOffset_Stable; - - // Internal data - - protected PopUpWindow m_ActivePopUp; - protected SketchControlsScript.GlobalCommands m_DelayedCommand; - protected int m_DelayedCommandParam; - protected int m_DelayedCommandParam2; - - protected GameObject m_PanelDescriptionObject; - protected Renderer m_PanelDescriptionRenderer; - protected TextMeshPro m_PanelDescriptionTextMeshPro; - - protected Vector3 m_BaseScale; - protected float m_AdjustedScale; - - protected TextSpring m_PanelDescriptionTextSpring; - protected TextSpring m_PanelFlairSpring; - protected PanelFlair m_PanelFlair; - - protected Vector3 m_ReticleOffset; - protected Vector3 m_Bounds; - protected Vector3 m_WorkingReticleBounds; - - protected DescriptionState m_PanelDescriptionState; - protected DescriptionState m_PanelFlairState; - protected float m_CloseAngleThreshold; - - protected PanelState m_CurrentState; - protected PanelState m_DesiredState; - protected bool m_GazeActive; - protected bool m_GazeWasActive; - protected bool m_GazeDescriptionsActive; - - protected bool m_InputValid; - protected bool m_EatInput; - protected Ray m_ReticleSelectionRay; - - protected float m_PositioningPercent; - - protected float m_MaxGazeOffsetDistance; - protected Vector3 m_GazeRotationAxis; - protected float m_GazeRotationAngle; - protected Quaternion m_GazeRotationAmount; - protected float m_GazeActivePercent; - - protected UIComponentManager m_UIComponentManager; - protected NonScaleChild m_NonScaleChild; // potentially null - - // Private - - private List m_DecorRenderers; - private List m_DecorTextMeshes; - - private float m_ScaledPositioningSphereRadius; - private float m_PositioningExtent; - private Vector3[] m_PositioningSpheres; - private Vector3[] m_PositioningSpheresTransformed; - - private Vector3 m_PositioningHome; - private float m_PositioningK = 0.5f; - private float m_PositioningDampen = 0.1f; - private float m_DepenetrationScalar = 200.0f; - private Vector3 m_PositioningVelocity; - - private Vector3 m_GazeHitPositionCurrent; - private Vector3 m_GazeHitPositionDesired; - private float m_GazeHitPositionSpeed = 10.0f; - - protected Vector2 m_SwipeRecentMotion = Vector2.zero; - - private FixedTransitionState m_TransitionState; - private TrTransform m_WandTransitionTarget; - private static float m_WandTransitionDuration = .25f; - private float m_WandTransitionPercent; // 0 = on wand, 1 = at target - private float m_WandAttachAdjustSpeed = 16.0f; - private float m_WandAttachYOffset_Initial; - private float m_WandAttachAngle_Initial; - private PanelWidget m_WidgetSibling; - - private GameObject m_TempPopUpCollider; - private float m_PopUpGazeTimer; - - private bool m_AdvancedModePanel; - private bool m_CurrentlyVisibleInAdvancedMode; - - // TODO: The following are just to track down an elusive NRE. Delete when we've figured - // it out. - private bool m_PanelInitializationStarted; - private bool m_PanelInitializationFinished; - private float m_PanelDescriptionCounter; - public Action m_OverrideControllerMaterial; - - // Accessors/properties - - public Vector3 GetBounds() { return m_Bounds; } - public float GetPositioningExtent() { return m_PositioningExtent; } - public bool IsAvailable() { return m_CurrentState != PanelState.Unavailable; } - public bool IsActive() { return m_GazeActive; } - public bool BeginFixed { get { return m_BeginFixed; } } - public void ClearBeginFixed() { m_BeginFixed = false; } - public bool CanBeDetached { get { return m_CanBeDetachedFromWand; } } - public bool IsInInitialPosition() - { - return m_WandAttachYOffset == m_WandAttachYOffset_Initial && - m_WandAttachAngle == m_WandAttachAngle_Initial; - } - public PanelWidget WidgetSibling { get { return m_WidgetSibling; } } - public bool AdvancedModePanel { get { return m_AdvancedModePanel; } } - public bool CurrentlyVisibleInAdvancedMode { get { return m_CurrentlyVisibleInAdvancedMode; } } - public Vector3 ParticleBounds { get { return m_ParticleBounds; } } - public PopUpWindow PanelPopUp { get { return m_ActivePopUp; } } - - public Color GetGazeColorFromActiveGazePercent() - { - PanelManager pm = PanelManager.m_Instance; - return Color.Lerp(pm.PanelHighlightInactiveColor, pm.PanelHighlightActiveColor, - m_GazeActivePercent); - } - - public PanelType Type - { - get { return m_PanelType; } - } - - public virtual bool ShouldRegister { get { return true; } } - - public void InitAdvancedFlag(bool advanced) - { - m_AdvancedModePanel = advanced; - m_CurrentlyVisibleInAdvancedMode = m_BeginFixed; - } - - public float PopUpOffset - { - get { return m_ActivePopUp ? m_ActivePopUp.GetPopUpForwardOffset() : 0; } - } - - virtual protected void CalculateBounds() - { - Vector3 vCurrentScale = transform.localScale; - m_Bounds = m_ReticleBounds; - m_Bounds.x *= vCurrentScale.x * 0.5f; - m_Bounds.y *= vCurrentScale.y * 0.5f; - m_Bounds.z = 0.0f; - - if (m_ActivePopUp == null) - { - m_WorkingReticleBounds = m_Bounds; - } - else - { - Vector3 vPopUpCurrentScale = m_ActivePopUp.transform.localScale; - m_WorkingReticleBounds = m_ActivePopUp.GetReticleBounds(); - m_WorkingReticleBounds.x *= vPopUpCurrentScale.x * 0.5f; - m_WorkingReticleBounds.y *= vPopUpCurrentScale.y * 0.5f; - } - } - - public void ActivatePromoBorder(bool activate) - { - if (m_WidgetSibling) - { - if (activate) - { - m_WidgetSibling.RemovePromoMeshesFromTintable(m_PromoBorders); - } - else - { - m_WidgetSibling.AddPromoMeshesToTintable(m_PromoBorders); - } - } - foreach (var m in m_PromoBorders) - { - m.material = activate ? PromoManager.m_Instance.SharePromoMaterial : m_BorderMaterial; - } - } - - virtual public void SetInIntroMode(bool inIntro) { } - - public void SetPositioningPercent(float fPercent) - { - m_PositioningPercent = fPercent; - } - - public void SetScale(float fScale) - { - m_AdjustedScale = fScale; - transform.localScale = m_BaseScale * m_AdjustedScale; - } - - public bool PanelIsUsed() { return m_CurrentState != PanelState.Unused; } - - public Collider GetCollider() { return m_Collider; } - - public bool HasMeshCollider() - { - return m_MeshCollider != null; - } - - virtual public bool RaycastAgainstMeshCollider(Ray rRay, out RaycastHit rHitInfo, float fDist) - { - rHitInfo = new RaycastHit(); - bool bReturnValue = false; - - // Creating a popup when a popup exists will generate a temp collider. This is to prevent - // forced, accidental out of bounds user input. - if (m_TempPopUpCollider != null) - { - BoxCollider tempCollider = m_TempPopUpCollider.GetComponent(); - bReturnValue = tempCollider.Raycast(rRay, out rHitInfo, fDist); - if (!bReturnValue) - { - // If we're ever not pointing at the temp collider, destroy it. - Destroy(m_TempPopUpCollider); - m_TempPopUpCollider = null; - } - } - - // If we've got a pop-up, check collision against that guy first. - if (m_ActivePopUp != null) - { - var collider = m_ActivePopUp.GetCollider(); - if (collider == null) { throw new InvalidOperationException("No popup collider"); } - bReturnValue = bReturnValue || - m_ActivePopUp.GetCollider().Raycast(rRay, out rHitInfo, fDist); - } - - // Check custom colliders on components. - bReturnValue = bReturnValue || - m_UIComponentManager.RaycastAgainstCustomColliders(rRay, out rHitInfo, fDist); - - // If we didn't have a pop-up, or collision failed, default to base mesh. - if (m_MeshCollider == null) { throw new InvalidOperationException("No mesh collider"); } - bReturnValue = bReturnValue || m_MeshCollider.Raycast(rRay, out rHitInfo, fDist); - return bReturnValue; - } - - virtual public void AssignControllerMaterials(InputManager.ControllerName controller) - { - m_UIComponentManager.AssignControllerMaterials(controller); - - // Allows components to override the regular controller material - // without worrying about execution order etc - if (m_OverrideControllerMaterial != null) - { - m_OverrideControllerMaterial(); - // Clear afterwards. This needs to be set every frame - m_OverrideControllerMaterial = null; - } - } - - /// This function is used to determine the value to be passed in to the controller pad mesh's - /// shader for visualizing swipes and other actions. - /// It is called by SketchControls when the panel is in focus. - public float GetControllerPadShaderRatio(InputManager.ControllerName controller) - { - return m_UIComponentManager.GetControllerPadShaderRatio(controller); - } - - public bool BrushPadAnimatesOnHover() - { - return m_UIComponentManager.BrushPadAnimatesOnAnyHover(); - } - - public bool UndoRedoBlocked() - { - // This function could be generalized to allow specific UIComponents to block undo/redo, - // but we only need it in a single case right now, so it's a bit more specific. - return m_ActivePopUp == null ? false : m_ActivePopUp.BlockUndoRedo(); - } - - virtual public void OnPanelMoved() { } - - virtual protected void Awake() - { - m_WandAttachYOffset_Initial = m_WandAttachYOffset; - m_WandAttachAngle_Initial = m_WandAttachAngle; - m_WandAttachYOffset_Target = m_WandAttachYOffset; - } - - // Happens at App Start() time. - virtual public void InitPanel() - { - m_PanelInitializationStarted = true; - m_BorderMaterial = m_Border.material; - m_BaseScale = transform.localScale; - m_AdjustedScale = 1.0f; - - CalculateBounds(); - m_NonScaleChild = GetComponent(); - - if (m_PanelDescriptionPrefab != null) - { - m_PanelDescriptionObject = (GameObject)Instantiate(m_PanelDescriptionPrefab); - m_PanelDescriptionObject.transform.position = m_Mesh.transform.position; - m_PanelDescriptionObject.transform.rotation = m_Mesh.transform.rotation; - m_PanelDescriptionObject.transform.SetParent(transform); - Vector3 vScale = m_PanelDescriptionObject.transform.localScale; - vScale *= transform.localScale.x; - m_PanelDescriptionObject.transform.localScale = vScale; - - m_PanelDescriptionRenderer = m_PanelDescriptionObject.GetComponent(); - if (m_PanelDescriptionRenderer) - { - m_PanelDescriptionRenderer.enabled = false; - } - - m_PanelDescriptionTextMeshPro = m_PanelDescriptionObject.GetComponent(); - if (m_PanelDescriptionTextMeshPro) - { - m_PanelDescriptionTextMeshPro.text = PanelDescription; - m_PanelDescriptionTextMeshPro.color = m_PanelDescriptionColor; - } - LocalizationSettings.SelectedLocaleChanged += OnSelectedLocaleChanged; - } - - if (m_PanelFlairPrefab != null) - { - GameObject go = (GameObject)Instantiate(m_PanelFlairPrefab); - m_PanelFlair = go.GetComponent(); - m_PanelFlair.ParentToPanel(transform, m_PanelFlairOffset); - } - - m_PanelDescriptionState = DescriptionState.Closing; - m_PanelFlairState = DescriptionState.Closing; - - m_CloseAngleThreshold = Mathf.Abs(m_DescriptionOpenAngle - m_DescriptionClosedAngle) * 0.01f; - - m_PanelDescriptionTextSpring = new TextSpring(); - m_PanelDescriptionTextSpring.m_CurrentAngle = m_DescriptionClosedAngle; - m_PanelDescriptionTextSpring.m_DesiredAngle = m_DescriptionClosedAngle; - m_PanelFlairSpring = new TextSpring(); - m_PanelFlairSpring.m_CurrentAngle = m_DescriptionClosedAngle; - m_PanelFlairSpring.m_DesiredAngle = m_DescriptionClosedAngle; - - PanelManager pm = PanelManager.m_Instance; - m_Border.material.SetColor("_Color", pm.PanelHighlightInactiveColor); - - m_DecorRenderers = new List(); - m_DecorTextMeshes = new List(); - - if (m_Decor.Length > 0) - { - // Cache all decor renderers. - for (int i = 0; i < m_Decor.Length; ++i) - { - Renderer[] aChildRenderers = m_Decor[i].GetComponentsInChildren(); - for (int j = 0; j < aChildRenderers.Length; ++j) - { - // Prefer to cache a text mesh pro object if we find one. - TextMeshPro tmp = aChildRenderers[j].GetComponent(); - if (tmp) - { - m_DecorTextMeshes.Add(tmp); - } - else - { - // Otherwise, the standard renderer will do. - m_DecorRenderers.Add(aChildRenderers[j]); - m_DecorRenderers[m_DecorRenderers.Count - 1].material.SetColor("_Color", - pm.PanelHighlightInactiveColor); - } - } - } - } - - m_CurrentState = PanelState.Available; - m_DesiredState = PanelState.Available; - m_GazeActive = false; - m_PositioningPercent = 0.0f; - - if (m_PositioningSpheresBounds.x > 0.0f && m_PositioningSpheresBounds.y > 0.0f && m_PositioningSphereRadius > 0.0f) - { - Vector2 vSphereBounds = m_PositioningSpheresBounds; - vSphereBounds.x -= m_PositioningSphereRadius * 0.5f; - vSphereBounds.y -= m_PositioningSphereRadius * 0.5f; - m_ScaledPositioningSphereRadius = m_PositioningSphereRadius * transform.localScale.x; - - int iNumSpheresWidth = Mathf.CeilToInt((vSphereBounds.x * 2.0f) / m_PositioningSphereRadius); - int iNumSpheresHeight = Mathf.CeilToInt((vSphereBounds.y * 2.0f) / m_PositioningSphereRadius); - int iTotalNumSpheres = (iNumSpheresWidth * 2) + ((iNumSpheresHeight - 2) * 2); - m_PositioningSpheres = new Vector3[iTotalNumSpheres]; - - float fXInterval = (vSphereBounds.x / (float)(iNumSpheresWidth - 1)) * 2.0f; - float fYInterval = (vSphereBounds.y / (float)(iNumSpheresHeight - 1)) * 2.0f; - for (int i = 0; i < iNumSpheresWidth; ++i) - { - float fX = -vSphereBounds.x + (fXInterval * (float)i); - m_PositioningSpheres[i].Set(fX, -vSphereBounds.y, 0.0f); - } - for (int i = 0; i < iNumSpheresHeight - 2; ++i) - { - float fY = -vSphereBounds.y + (fYInterval * (float)(i + 1)); - m_PositioningSpheres[iNumSpheresWidth + (i * 2)].Set(-vSphereBounds.x, fY, 0.0f); - m_PositioningSpheres[iNumSpheresWidth + (i * 2) + 1].Set(vSphereBounds.x, fY, 0.0f); - } - for (int i = iTotalNumSpheres - iNumSpheresWidth; i < iTotalNumSpheres; ++i) - { - int iIndex = i - (iTotalNumSpheres - iNumSpheresWidth); - float fX = -vSphereBounds.x + (fXInterval * (float)iIndex); - m_PositioningSpheres[i].Set(fX, vSphereBounds.y, 0.0f); - } - - m_PositioningSpheresTransformed = new Vector3[m_PositioningSpheres.Length]; - for (int i = 0; i < m_PositioningSpheresTransformed.Length; ++i) - { - m_PositioningSpheresTransformed[i] = new Vector3(); - m_PositioningExtent = Mathf.Max(m_PositioningExtent, Mathf.Max(m_PositioningSpheres[i].x, m_PositioningSpheres[i].y)); - } - m_PositioningExtent += (m_PositioningSphereRadius * 2.0f); - } - - m_MaxGazeOffsetDistance = m_Bounds.magnitude; - m_GazeRotationAmount = Quaternion.identity; - - m_UIComponentManager = GetComponent(); - m_UIComponentManager.SetColor(pm.PanelHighlightInactiveColor); - - m_WidgetSibling = GetComponent(); - if (m_Fixed) - { - m_TransitionState = FixedTransitionState.Fixed; - } - - // Bake border meshs. - float width = !m_AdvancedModePanel ? m_BorderMeshAdvWidth : m_BorderMeshWidth; - Color baseCol = !m_AdvancedModePanel ? pm.PanelBorderMeshOutlineColor : pm.PanelBorderMeshBaseColor; - Color outlineCol = !m_AdvancedModePanel ? pm.PanelBorderMeshBaseColor : pm.PanelBorderMeshOutlineColor; - BakedMeshOutline[] bakeries = GetComponentsInChildren(true); - BakedMeshOutline borderBakery = m_Border.GetComponent(); - for (int i = 0; i < bakeries.Length; ++i) - { - if (bakeries[i] == borderBakery) - { - // The border is the only bakery that gets custom treatment. - bakeries[i].Bake(baseCol, outlineCol, width); - } - else - { - bakeries[i].Bake(pm.PanelBorderMeshBaseColor, pm.PanelBorderMeshOutlineColor, m_BorderMeshWidth); - } - } - - m_PanelInitializationFinished = true; - } - - public void CloseActivePopUp(bool force) - { - if (m_ActivePopUp != null) - { - if (m_ActivePopUp.RequestClose(force)) - { - InvalidateIfActivePopup(m_ActivePopUp); - } - } - } - - public void VerifyStateForFloating() - { - m_TransitionState = FixedTransitionState.Floating; - m_WandTransitionPercent = 1; - } - - public void SetPanelStableToTarget() - { - m_WandAttachYOffset_Stable = m_WandAttachYOffset_Target; - } - - public void ResetPanelToInitialPosition() - { - m_WandAttachYOffset = m_WandAttachYOffset_Initial; - m_WandAttachYOffset_Target = m_WandAttachYOffset_Initial; - m_WandAttachYOffset_Stable = m_WandAttachYOffset_Initial; - m_WandAttachAngle = m_WandAttachAngle_Initial; - - if (m_TransitionState != FixedTransitionState.Fixed) - { - m_Fixed = true; - m_TransitionState = FixedTransitionState.Fixed; - m_WandTransitionPercent = 0; - } - } - - public void ResetPanel() - { - // Get rid of the popup as fast as possible. - if (m_ActivePopUp != null) - { - Destroy(m_ActivePopUp.gameObject); - InvalidateIfActivePopup(m_ActivePopUp); - } - Destroy(m_TempPopUpCollider); - m_TempPopUpCollider = null; - - //reset gaze animations - m_PanelDescriptionState = DescriptionState.Closed; - if (m_PanelDescriptionRenderer) - { - m_PanelDescriptionRenderer.enabled = false; - } - - m_PanelFlairState = DescriptionState.Closed; - if (m_PanelFlair != null) - { - m_PanelFlair.Hide(); - } - - UpdatePanelColor(PanelManager.m_Instance.PanelHighlightInactiveColor); - - m_GazeActive = false; - m_GazeActivePercent = 0.0001f; - m_GazeRotationAxis = Vector3.zero; - } - - public void InvalidateIfActivePopup(PopUpWindow activePopup) - { - // If this popup isn't the active one, don't bother. - if (activePopup == m_ActivePopUp) - { - m_ActivePopUp = null; - // Eat input when we close a popup so the close action doesn't carry over. - m_EatInput = true; - } - } - - private void OnSelectedLocaleChanged(Locale locale) - { - if (m_PanelDescriptionTextMeshPro) - { - m_PanelDescriptionTextMeshPro.text = PanelDescription; - } - } - - private void OnDestroy() - { - LocalizationSettings.SelectedLocaleChanged -= OnSelectedLocaleChanged; - } - - void OnEnable() - { - OnEnablePanel(); - } - - void OnDisable() - { - OnDisablePanel(); - } - - virtual protected void OnEnablePanel() - { - if (PanelManager.m_Instance != null) - { - if (PanelManager.m_Instance.AdvancedModeActive()) - { - m_CurrentlyVisibleInAdvancedMode = true; - } - } - } - - virtual protected void OnDisablePanel() - { - if (PanelManager.m_Instance != null) - { - if (PanelManager.m_Instance.AdvancedModeActive()) - { - m_CurrentlyVisibleInAdvancedMode = false; - } - } - } - - public void ResetReticleOffset() - { - m_ReticleOffset = Vector3.zero; - } - - public void UpdateReticleOffset(float fXDelta, float fYDelta) - { - m_ReticleOffset.x += fXDelta * m_PanelSensitivity; - m_ReticleOffset.y += fYDelta * m_PanelSensitivity; - - if (m_ClampToBounds) - { - m_ReticleOffset.x = Mathf.Clamp(m_ReticleOffset.x, -m_WorkingReticleBounds.x, m_WorkingReticleBounds.x); - m_ReticleOffset.y = Mathf.Clamp(m_ReticleOffset.y, -m_WorkingReticleBounds.y, m_WorkingReticleBounds.y); - m_ReticleOffset.z = m_WorkingReticleBounds.z; - } - } - - // Given a position that has been proven to be a hit point on the panel's collider and the cast - // direction that resulted in that point, determine where the reticle should be located. - // Used by wand panel method of interacting with panels. - virtual public void GetReticleTransformFromPosDir(Vector3 vInPos, Vector3 vInDir, out Vector3 vOutPos, out Vector3 vForward) - { - //by default, the collision point is ok, and the reticle's forward should be the same as the mesh - vOutPos = vInPos; - vForward = -m_Mesh.transform.forward; - - Vector3 dir = Vector3.forward; - Ray rCastRay = new Ray(vInPos - vInDir * 0.5f, vInDir); - - // If we have a ghost popup, collide with that to find our position. - if (m_TempPopUpCollider != null) - { - RaycastHit rHitInfo; - if (DoesRayHitCollider(rCastRay, m_TempPopUpCollider.GetComponent(), out rHitInfo)) - { - vOutPos = rHitInfo.point; - } - } - - // Override default and ghost with standard popup collision. - if (m_ActivePopUp != null) - { - m_ActivePopUp.CalculateReticleCollision(rCastRay, ref vOutPos, ref vForward); - } - else - { - // PopUps trump UIComponents, so if there isn't a PopUp, check against all UIComponents. - m_UIComponentManager.CalculateReticleCollision(rCastRay, ref vOutPos, ref vForward); - } - } - - // TODO : This is currently broken. Needs to be updated to use new - // m_UIComponentManager.CalculateReticleCollision style. - // Using m_ReticleOffset, determine where the reticle should be located. - // Used by gaze method of interacting with panels. - virtual public void GetReticleTransform(out Vector3 vPos, out Vector3 vForward, bool bGazeAndTap) - { - // For ViewingOnly controls, position the reticle at the gaze panel position - if (bGazeAndTap) - { - // Calculate plane intersection - Transform head = ViewpointScript.Head; - Ray ray = new Ray(head.position, head.forward); - RaycastHit rHitInfo; - if (RaycastAgainstMeshCollider(ray, out rHitInfo, GAZE_DISTANCE)) - { - vPos = rHitInfo.point; - } - else - { - vPos = new Vector3(LARGE_DISTANCE, LARGE_DISTANCE, LARGE_DISTANCE); - } - } - else - { - Vector3 vTransformedOffset = m_Mesh.transform.rotation * m_ReticleOffset; - vPos = transform.position + vTransformedOffset; - } - vForward = -m_Mesh.transform.forward; - } - - // This function should only be used when the app state changes in a way that requires - // an out-of-focus panel's visuals to become reflect a stale state. - virtual public void ForceUpdatePanelVisuals() - { - m_UIComponentManager.UpdateVisuals(); - } - - void Update() - { - BaseUpdate(); - } - - protected void BaseUpdate() - { - UpdateState(); - CalculateBounds(); - UpdateDescriptions(); - UpdateGazeBehavior(); - UpdateFixedTransition(); - } - - protected void UpdateState() - { - //check if we're switching activity - if (m_GazeWasActive != m_GazeActive) - { - if (m_GazeActive) - { - AudioManager.m_Instance.ActivatePanel(true, transform.position); - } - else - { - m_UIComponentManager.ResetInput(); - AudioManager.m_Instance.ActivatePanel(false, transform.position); - } - - m_GazeWasActive = m_GazeActive; - OnUpdateActive(); - } - - bool bGazeDescriptionsWereActive = m_GazeDescriptionsActive; - m_GazeDescriptionsActive = m_GazeActive; - - // Update components if gaze is active. - if (m_GazeDescriptionsActive) - { - m_UIComponentManager.UpdateVisuals(); - } - - //check if we're switching descriptions showing - if (bGazeDescriptionsWereActive != m_GazeDescriptionsActive) - { - if (m_GazeDescriptionsActive) - { - if (m_PanelDescriptionObject) - { - m_PanelDescriptionState = DescriptionState.Open; - m_PanelDescriptionTextSpring.m_DesiredAngle = m_DescriptionOpenAngle; - m_PanelDescriptionRenderer.enabled = true; - } - } - else - { - if (m_PanelDescriptionObject) - { - m_PanelDescriptionState = DescriptionState.Closing; - m_PanelDescriptionTextSpring.m_DesiredAngle = m_DescriptionClosedAngle; - ResetPanelFlair(); - } - m_UIComponentManager.ManagerLostFocus(); - m_UIComponentManager.Deactivate(); - if (m_ActivePopUp != null) - { - if (m_ActivePopUp.RequestClose()) - { - InvalidateIfActivePopup(m_ActivePopUp); - } - } - } - } - - //update state - m_CurrentState = m_DesiredState; - } - - virtual protected void OnUpdateActive() - { - } - - void UpdateMeshRotation() - { - m_Mesh.transform.rotation = m_GazeRotationAmount * transform.rotation; - } - - protected void UpdateDescriptions() - { - try - { - m_PanelDescriptionCounter = 0; - if (m_PanelDescriptionState != DescriptionState.Closed && m_PanelDescriptionObject != null) - { - m_PanelDescriptionCounter = 1; - m_PanelDescriptionTextSpring.Update(m_DescriptionSpringK, m_DescriptionSpringDampen); - - m_PanelDescriptionCounter = 2; - Quaternion qOrient = Quaternion.Euler(0.0f, m_PanelDescriptionTextSpring.m_CurrentAngle, 0.0f); - m_PanelDescriptionObject.transform.rotation = m_Mesh.transform.rotation * qOrient; - - m_PanelDescriptionCounter = 3; - Vector3 vPanelDescriptionOffset = m_Bounds; - vPanelDescriptionOffset.x *= m_PanelDescriptionOffset.x; - vPanelDescriptionOffset.y *= m_PanelDescriptionOffset.y; - Vector3 vTransformedOffset = m_Mesh.transform.rotation * vPanelDescriptionOffset; - m_PanelDescriptionObject.transform.position = m_Mesh.transform.position + vTransformedOffset; - - m_PanelDescriptionCounter = 4; - float fDistToClosed = Mathf.Abs(m_PanelDescriptionTextSpring.m_CurrentAngle - m_DescriptionClosedAngle); - Color descColor = m_PanelDescriptionColor; - if (m_ActivePopUp != null) - { - descColor = Color.Lerp(m_PanelDescriptionColor, - PanelManager.m_Instance.PanelHighlightInactiveColor, - m_ActivePopUp.GetTransitionRatioForVisuals()); - } - float fRatio = fDistToClosed / m_DescriptionAlphaDistance; - descColor.a = Mathf.Min(fRatio * fRatio, 1.0f); - if (m_PanelDescriptionTextMeshPro) - { - m_PanelDescriptionTextMeshPro.color = descColor; - } - - m_PanelDescriptionCounter = 5; - if (m_PanelDescriptionState == DescriptionState.Closing) - { - float fToDesired = m_PanelDescriptionTextSpring.m_DesiredAngle - m_PanelDescriptionTextSpring.m_CurrentAngle; - if (Mathf.Abs(fToDesired) <= m_CloseAngleThreshold) - { - m_PanelDescriptionRenderer.enabled = false; - m_PanelDescriptionState = DescriptionState.Closed; - } - } - } - - m_PanelDescriptionCounter = 6; - if (m_PanelFlairState != DescriptionState.Closed) - { - m_PanelDescriptionCounter = 7; - m_PanelFlairSpring.Update(m_DescriptionSpringK, m_DescriptionSpringDampen); - float fDistToClosed = Mathf.Abs(m_PanelFlairSpring.m_CurrentAngle - m_DescriptionClosedAngle); - float fRatio = fDistToClosed / m_DescriptionAlphaDistance; - float fAlpha = Mathf.Min(fRatio * fRatio, 1.0f); - - m_PanelDescriptionCounter = 8; - Quaternion qOrient = m_Mesh.transform.rotation * Quaternion.Euler(0.0f, m_PanelFlairSpring.m_CurrentAngle, 0.0f); - - m_PanelDescriptionCounter = 9; - if (m_PanelFlair != null) - { - m_PanelFlair.UpdateAnimationOnPanel(m_Bounds, qOrient, fAlpha); - } - - m_PanelDescriptionCounter = 10; - if (m_PanelFlairState == DescriptionState.Closing) - { - float fToDesired = m_PanelFlairSpring.m_DesiredAngle - m_PanelFlairSpring.m_CurrentAngle; - if (Mathf.Abs(fToDesired) <= m_CloseAngleThreshold) - { - if (m_PanelFlair != null) - { - m_PanelFlair.Hide(); - } - - m_PanelFlairState = DescriptionState.Closed; - } - } - } - } - catch (Exception ex) - { - string message = string.Format("{0}: Init State({1}, {2}), Counter({3})", - ex.Message, - m_PanelInitializationStarted, - m_PanelInitializationFinished, - m_PanelDescriptionCounter); - throw new Exception(message); - } - } - - protected virtual void UpdateGazeBehavior() - { - if (m_UseGazeRotation && m_Mesh) - { - float fPrevPercent = m_GazeActivePercent; - float fPercentStep = m_GazeActivateSpeed * Time.deltaTime; - if (IsActive()) - { - m_GazeActivePercent = Mathf.Min(m_GazeActivePercent + fPercentStep, 1.0f); - } - else - { - m_GazeActivePercent = Mathf.Max(m_GazeActivePercent - fPercentStep, 0.0f); - } - - //don't bother updating static panels - if (fPrevPercent > 0.0f) - { - float fRotationAngle = m_GazeRotationAngle * m_GazeActivePercent * (1.0f - m_PositioningPercent); - m_GazeRotationAmount = Quaternion.AngleAxis(fRotationAngle, m_GazeRotationAxis); - UpdateMeshRotation(); - - Color rPanelColor = GetGazeColor(); - if (m_Border.material == m_BorderMaterial) - { - m_Border.material.SetColor("_Color", rPanelColor); - } - - if (fPrevPercent < 1.0f) - { - float fScaleMult = m_GazeActivePercent * (m_GazeHighlightScaleMultiplier - 1.0f); - Vector3 newScale = m_BaseScale * m_AdjustedScale * (1.0f + fScaleMult); - if (m_NonScaleChild != null) - { - m_NonScaleChild.globalScale = newScale; - } - else - { - transform.localScale = newScale; - } - } - - UpdatePanelColor(rPanelColor); - m_UIComponentManager.GazeRatioChanged(m_GazeActivePercent); - } - } - } - - public Color GetGazeColor() - { - PanelManager pm = PanelManager.m_Instance; - Color targetColor = pm.PanelHighlightActiveColor; - if (m_ActivePopUp != null) - { - targetColor = Color.Lerp(pm.PanelHighlightActiveColor, - pm.PanelHighlightInactiveColor, - m_ActivePopUp.GetTransitionRatioForVisuals()); - } - - float t = m_GazeActivePercent; - if (SketchControlsScript.m_Instance.AtlasIconTextures) - { - // If we're atlasing panel textures, only send 0 and 1 through. - t = Mathf.Floor(m_GazeActivePercent + 0.5f); - } - return Color.Lerp(pm.PanelHighlightInactiveColor, targetColor, t); - } - - protected void UpdateFixedTransition() - { - // State machine for panel exploding off of wand controller. - if (m_TransitionState == FixedTransitionState.FixedToFloating) - { - m_WandTransitionPercent += Time.deltaTime / m_WandTransitionDuration; - if (m_WandTransitionPercent >= 1.0f) - { - m_WandTransitionPercent = 1.0f; - m_TransitionState = FixedTransitionState.Floating; - } - PanelManager.m_Instance.UpdateWandTransitionXf( - this, m_WandTransitionTarget, m_WandTransitionPercent); - } - else if (m_TransitionState == FixedTransitionState.FloatingToFixed) - { - m_WandTransitionPercent -= Time.deltaTime / m_WandTransitionDuration; - if (m_WandTransitionPercent <= 0.0f) - { - m_WandTransitionPercent = 0.0f; - m_TransitionState = FixedTransitionState.Fixed; - } - PanelManager.m_Instance.UpdateWandTransitionXf( - this, m_WandTransitionTarget, m_WandTransitionPercent); - } - else if (WidgetSibling && - WidgetSibling.IsUserInteracting(InputManager.ControllerName.Brush)) - { - // If the user is interacting with this panel, lock to a pane if this panel allows it. - if (m_CanBeFixedToWand) - { - PanelManager.m_Instance.AttachHeldPanelToWand(this); - } - } - else if (m_TransitionState == FixedTransitionState.Fixed) - { - // Update attach height. - float fStep = m_WandAttachAdjustSpeed * Time.deltaTime; - float fToTarget = m_WandAttachYOffset_Target - m_WandAttachYOffset; - if (Mathf.Abs(fToTarget) < fStep) - { - m_WandAttachYOffset = m_WandAttachYOffset_Target; - } - else - { - m_WandAttachYOffset += fStep * Mathf.Sign(fToTarget); - } - m_WandAttachRadiusAdjust = 0.0f; - } - } - - public void WidgetSiblingBeginInteraction() - { - PanelManager.m_Instance.InitPanesForPanelAttach(m_Fixed); - - // Initialize primed flag to off-- it'll get enabled if the attachment checks are valid. - m_WandPrimedForAttach = false; - - if (m_Fixed) - { - m_Fixed = false; - m_TransitionState = FixedTransitionState.Floating; - m_WandTransitionPercent = 1; - } - } - - public void WidgetSiblingEndInteraction() - { - if (!m_Fixed) - { - PanelManager.m_Instance.ResetPaneVisuals(); - if (m_WandPrimedForAttach || !CanBeDetached) - { - m_Fixed = true; - m_TransitionState = FixedTransitionState.Fixed; - m_WandTransitionPercent = 0; - } - - if (!m_WandPrimedForAttach) - { - // If we're releasing this panel and it's not snapping to a pane, make sure the pane - // panels are reset back to their stable positions. - PanelManager.m_Instance.SetFixedPanelsToStableOffsets(); - } - else - { - // If this panel is snapping to a pane, update it's stable position so it's sorted - // correctly when we close the gaps. - SetPanelStableToTarget(); - } - m_WandTransitionTarget = TrTransform.FromTransform(transform); - WidgetSibling.SetActiveTintToShowError(false); - - PanelManager.m_Instance.ClosePanePanelGaps(); - } - } - - // Target is ignored if the panel is reattaching to the wand - public void TransitionToWand(bool bFixed, TrTransform target) - { - if (bFixed && m_TransitionState != FixedTransitionState.Fixed) - { - m_TransitionState = FixedTransitionState.FloatingToFixed; - } - else if (!bFixed && m_TransitionState != FixedTransitionState.Floating) - { - m_WandTransitionTarget = target; - m_TransitionState = FixedTransitionState.FixedToFloating; - } - } - - void UpdatePanelColor(Color rPanelColor) - { - // Set the appropriate dim value for all our UI components. - m_UIComponentManager.SetColor(rPanelColor); - - OnUpdateGazeBehavior(rPanelColor); - - for (int i = 0; i < m_DecorRenderers.Count; ++i) - { - m_DecorRenderers[i].material.SetColor("_Color", rPanelColor); - } - for (int i = 0; i < m_DecorTextMeshes.Count; ++i) - { - m_DecorTextMeshes[i].color = rPanelColor; - } - } - - virtual protected void OnUpdateGazeBehavior(Color rPanelColor) { } - - virtual public void PanelGazeActive(bool bActive) - { - m_GazeActive = bActive; - m_GazeHitPositionCurrent = transform.position; - m_UIComponentManager.ResetInput(); - } - - void SetPanelFlairText(string sText) - { - if (m_PanelFlair != null) - { - // Interpret any message as a good message. - if (m_PanelFlair.AlwaysShow) - { - m_PanelFlair.SetText(sText); - m_PanelFlair.Show(); - m_PanelFlairState = DescriptionState.Open; - m_PanelFlairSpring.m_DesiredAngle = m_DescriptionOpenAngle; - } - else - { - if (sText != null && !sText.Equals("")) - { - m_PanelFlair.SetText(sText); - m_PanelFlair.Show(); - m_PanelFlairState = DescriptionState.Open; - m_PanelFlairSpring.m_DesiredAngle = m_DescriptionOpenAngle; - } - else if (m_PanelFlairState != DescriptionState.Closed) - { - m_PanelFlairState = DescriptionState.Closing; - m_PanelFlairSpring.m_DesiredAngle = m_DescriptionClosedAngle; - } - } - } - } - - public void ResetPanelFlair() - { - if (m_PanelFlairState != DescriptionState.Closed) - { - m_PanelFlairState = DescriptionState.Closing; - m_PanelFlairSpring.m_DesiredAngle = m_DescriptionClosedAngle; - } - } - - virtual public void OnWidgetShowAnimStart() { } - - virtual public void OnWidgetShowAnimComplete() { } - - virtual public void OnWidgetHide() { } - - /// Accumulates dpad input, and returns nonzero for a discrete swipe action. - /// Return value is 1 for "backward" swipe moving a page forward - /// and -1 for "forward" swipe moving a page backward. - protected int AccumulateSwipe() - { - int direction = 0; - if (InputManager.m_Instance.IsBrushScrollActive()) - { - // If our delta is beyond our trigger threshold, report it. - float fDelta = InputManager.m_Instance.GetAdjustedBrushScrollAmount(); - if (IncrementMotionAndCheckForSwipe(fDelta)) - { - direction = (int)Mathf.Sign(m_SwipeRecentMotion.x) * -1; - m_SwipeRecentMotion.x = 0.0f; - } - } - else - { - m_SwipeRecentMotion.x = 0.0f; - } - - return direction; - } - - /// Virtual so panels can interpret m_SwipeRecentMotion however they'd like. - virtual public bool IncrementMotionAndCheckForSwipe(float fMotion) - { - m_SwipeRecentMotion.x += fMotion; - return Mathf.Abs(m_SwipeRecentMotion.x) > m_SwipeThreshold; - } - - /// Panels are updated by SketchControls when they have focus. - public void UpdatePanel(Vector3 vToPanel, Vector3 vHitPoint) - { - // Validate input and cache it for this update. - m_InputValid = InputManager.m_Instance.GetCommand(InputManager.SketchCommands.Activate); - if (m_EatInput) - { - m_EatInput = m_InputValid; - m_InputValid = false; - } - - // Cache input ray for this update. - Vector3 vReticlePos = SketchControlsScript.m_Instance.GetUIReticlePos(); - m_ReticleSelectionRay = new Ray(vReticlePos - transform.forward, transform.forward); - - if (m_ActivePopUp != null) - { - var collider = m_ActivePopUp.GetCollider(); - if (collider == null) { throw new InvalidOperationException("No popup collider"); } - RaycastHit hitInfo; - - // If we're pointing at a popup, increment our gaze timer. - if (BasePanel.DoesRayHitCollider(m_ReticleSelectionRay, - m_ActivePopUp.GetCollider(), out hitInfo)) - { - if (m_ActivePopUp.IsOpen()) - { - m_PopUpGazeTimer += Time.deltaTime; - } - } - else if (!m_ActivePopUp.InputObjectHasFocus() && - (InputManager.m_Instance.GetCommandDown(InputManager.SketchCommands.Activate) || - m_PopUpGazeTimer > m_PopUpGazeDuration)) - { - // If we're not pointing at the popup and the user doesn't have focus on an element - // of the popup, dismiss the popup if we've pointed at it before, or there's input. - m_ActivePopUp.RequestClose(); - } - } - - if (m_UseGazeRotation) - { - m_GazeHitPositionDesired = vHitPoint; - Vector3 vCurrToDesired = m_GazeHitPositionDesired - m_GazeHitPositionCurrent; - float fStep = m_GazeHitPositionSpeed * Time.deltaTime; - if (vCurrToDesired.sqrMagnitude < fStep * fStep) - { - m_GazeHitPositionCurrent = m_GazeHitPositionDesired; - } - else - { - vCurrToDesired.Normalize(); - vCurrToDesired *= fStep; - m_GazeHitPositionCurrent += vCurrToDesired; - } - - Vector3 vToCenter = m_GazeHitPositionCurrent - GetCollider().transform.position; - float fOffsetDist = vToCenter.magnitude; - vToCenter.Normalize(); - m_GazeRotationAxis = Vector3.Cross(-vToPanel, vToCenter); - m_GazeRotationAxis.Normalize(); - m_GazeRotationAngle = (fOffsetDist / m_MaxGazeOffsetDistance) * m_MaxGazeRotation; - } - - // Update custom logic for panel. - OnUpdatePanel(vToPanel, vHitPoint); - - // Update UIComponents, with PopUps taking priority. - if (m_ActivePopUp) - { - if (!m_EatInput && m_PopUpGazeTimer > 0) - { - m_ActivePopUp.UpdateUIComponents(m_ReticleSelectionRay, m_InputValid, m_ActivePopUp.GetCollider()); - } - } - else - { - // TODO : I'm not convinced the 3rd parameter here should be the main collider. - // I think it might need to be the mesh collider. If so, the collider is only used in - // monoscopic mode and should be renamed appropriately. - m_UIComponentManager.UpdateUIComponents(m_ReticleSelectionRay, m_InputValid, GetCollider()); - - // If a popup was just spawned, clear our active UI component, as input will now be - // directed to the popup. - if (m_ActivePopUp) - { - m_UIComponentManager.ResetInput(); - } - - if (m_UIComponentManager.ActiveInputUIComponent == null) - { - SetPanelFlairText(null); - } - else - { - SetPanelFlairText(m_UIComponentManager.ActiveInputUIComponent.Description); - } - } - } - - /// Base level logic for updating panel. This should be called from any derived class. - virtual public void OnUpdatePanel(Vector3 vToPanel, Vector3 vHitPoint) { } - - public void InitForPanelMovement() - { - m_PositioningHome = transform.position; - m_PositioningVelocity.Set(0.0f, 0.0f, 0.0f); - m_WandAttachYOffset_Stable = m_WandAttachYOffset_Target; - } - - virtual public void PanelHasStoppedMoving() - { - m_GazeHitPositionCurrent = transform.position; - } - - public void CreatePopUp(SketchControlsScript.GlobalCommands rCommand, - int iCommandParam, int iCommandParam2, string sDelayedText = "", - Action delayedClose = null) - { - CreatePopUp(rCommand, iCommandParam, iCommandParam2, Vector3.zero, sDelayedText, delayedClose); - } - - public void CreatePopUp(SketchControlsScript.GlobalCommands rCommand, - int iCommandParam, int iCommandParam2, Vector3 vPopupOffset, string sDelayedText = "", - Action delayedClose = null) - { - bool bPopUpExisted = false; - Vector3 vPrevPopUpPos = Vector3.zero; - // If we've got an active popup, send it packing. - if (m_ActivePopUp != null) - { - // Create a copy of the collider so we don't pull the rug out from under the user. - m_TempPopUpCollider = m_ActivePopUp.DuplicateCollider(); - vPrevPopUpPos = m_ActivePopUp.transform.position; - CloseActivePopUp(false); - bPopUpExisted = true; - } - - if (m_ActivePopUp == null) - { - // Look for the appropriate popup for this command. - int iPopUpIndex = -1; - for (int i = 0; i < m_PanelPopUpMap.Length; ++i) - { - if (m_PanelPopUpMap[i].m_Command == rCommand) - { - iPopUpIndex = i; - break; - } - } - - if (iPopUpIndex >= 0) - { - Vector3 position = vPopupOffset; - CreatePopUp( - m_PanelPopUpMap[iPopUpIndex].m_PopUpPrefab, position, - bPopUpExisted, bPopUpExisted, iCommandParam, - iCommandParam2, rCommand, sDelayedText, delayedClose - ); - } - } - } - - public void CreatePopUp( - GameObject prefab, Vector3 position, - bool explicitPosition, bool transition, int iCommandParam = -1, int iCommandParam2 = -1, - SketchControlsScript.GlobalCommands delayedCommand = SketchControlsScript.GlobalCommands.Null, - string sDelayedText = "", Action delayedClose = null) - { - // Create a new popup. - GameObject popUp = Instantiate(prefab, - m_Mesh.transform.position, m_Mesh.transform.rotation); - m_ActivePopUp = popUp.GetComponent(); - - if (explicitPosition) - { - popUp.transform.position = position; - } - else - { - // Treat position as an offset - popUp.transform.position = m_Mesh.transform.position + - (m_Mesh.transform.forward * m_ActivePopUp.GetPopUpForwardOffset()) + - m_Mesh.transform.TransformVector(position); - } - - popUp.transform.parent = m_Mesh.transform; - m_ActivePopUp.Init(gameObject, sDelayedText); - m_ActivePopUp.SetPopupCommandParameters(iCommandParam, iCommandParam2); - - m_ActivePopUp.m_OnClose += delayedClose; - m_PopUpGazeTimer = 0; - m_EatInput = !m_ActivePopUp.IsLongPressPopUp(); - - // If we closed a popup to create this one, we wan't don't want the standard visual - // fade that happens when a popup comes in. We're spoofing the transition value - // for visuals to avoid a pop. - if (!transition) - { - m_ActivePopUp.SpoofTransitionValue(); - } - - // Cache the intended command. - m_DelayedCommand = delayedCommand; - m_DelayedCommandParam = iCommandParam; - m_DelayedCommandParam2 = iCommandParam2; - - } - - public void PositionPopUp(Vector3 basePos) - { - m_ActivePopUp.transform.position = basePos; - } - - public void ResolveDelayedButtonCommand(bool bConfirm, bool bKeepOpen = false) - { - PopUpWindow currentPopup = m_ActivePopUp; - if (bConfirm) - { - SketchControlsScript.m_Instance.IssueGlobalCommand( - m_DelayedCommand, m_DelayedCommandParam, m_DelayedCommandParam2); - } - // if the popup has changed since the start of the function (and it wasn't null at the start), - // that means that the global command called kicked off a new popup. In which case we shouldn't - // close the popup, or overwrite the delayed command. - bool panelChanged = (currentPopup != null) && (m_ActivePopUp != currentPopup); - if (!panelChanged) - { - m_DelayedCommand = SketchControlsScript.GlobalCommands.Null; - m_DelayedCommandParam = -1; - m_DelayedCommandParam2 = -1; - if (m_ActivePopUp != null && !bKeepOpen) - { - m_ActivePopUp.RequestClose(); - } - } - } - - virtual public void GotoPage(int iIndex) - { - } - - virtual public void AdvancePage(int iAmount) - { - } - - public void InitForCollisionDetection() - { - for (int i = 0; i < m_PositioningSpheresTransformed.Length; ++i) - { - m_PositioningSpheresTransformed[i] = transform.TransformPoint(m_PositioningSpheres[i]); - } - } - - public void CalculateDepenetration(BasePanel rOther) - { - Vector3 vThemToUs = transform.position - rOther.transform.position; - Vector3 vThemToUsNorm = vThemToUs.normalized; - float fMaxExtent = m_PositioningExtent + rOther.GetPositioningExtent(); - - if (vThemToUs.sqrMagnitude < fMaxExtent * fMaxExtent) - { - float fCombinedSphereRad = m_ScaledPositioningSphereRadius + rOther.m_ScaledPositioningSphereRadius; - float fCombinedSphereRadSq = fCombinedSphereRad * fCombinedSphereRad; - for (int i = 0; i < m_PositioningSpheresTransformed.Length; ++i) - { - for (int j = 0; j < rOther.m_PositioningSpheresTransformed.Length; ++j) - { - Vector3 vSphereToSphere = rOther.m_PositioningSpheresTransformed[j] - m_PositioningSpheresTransformed[i]; - if (vSphereToSphere.sqrMagnitude < fCombinedSphereRadSq) - { - float fSphereToSphereDist = vSphereToSphere.magnitude; - float fDepenetrationAmount = fCombinedSphereRad - fSphereToSphereDist; - m_PositioningVelocity += (vThemToUsNorm * fDepenetrationAmount * m_DepenetrationScalar * Time.deltaTime); - } - } - } - } - } - - public void CalculateDepenetration(Vector3 vOtherPos, float fCombinedRadius) - { - Vector3 vThemToUs = transform.position - vOtherPos; - if (vThemToUs.sqrMagnitude < fCombinedRadius * fCombinedRadius) - { - float fDepenetrationAmount = fCombinedRadius - vThemToUs.magnitude; - m_PositioningVelocity += (vThemToUs.normalized * fDepenetrationAmount * - m_DepenetrationScalar * Time.fixedDeltaTime); - } - } - - public void UpdatePositioningForces() - { - //use spring to bring us home - Vector3 vToHome = m_PositioningHome - transform.position; - vToHome *= m_PositioningK; - Vector3 vDampenedVel = m_PositioningVelocity * m_PositioningDampen; - Vector3 vSpringForce = vToHome - vDampenedVel; - m_PositioningVelocity += vSpringForce; - - //update position - Vector3 vPos = transform.position; - vPos += (m_PositioningVelocity * Time.deltaTime); - transform.position = vPos; - if (m_NonScaleChild) - { - m_NonScaleChild.OnPosRotChanged(); - } - } - - /// Update the delayed command parameter that is used when a popup confirmation button is pressed. - /// This can be used when something provides more context to the initial command. - public void UpdateDelayedCommandParameter(int newParam) - { - m_DelayedCommandParam = newParam; - } - - static public bool DoesRayHitCollider(Ray rRay, Collider rCollider, bool skipAngleCheck = false) - { - if (!skipAngleCheck && Vector3.Angle(rRay.direction, rCollider.transform.forward) > 90.0f) - { - return false; - } - - RaycastHit rHitInfo; - return rCollider.Raycast(rRay, out rHitInfo, 100.0f); - } - - static public bool DoesRayHitCollider(Ray rRay, Collider rCollider, out RaycastHit rHitInfo) - { - return rCollider.Raycast(rRay, out rHitInfo, 100.0f); - } - - /* - * For Debugging. - * - void OnDrawGizmos() { - if (m_PositioningSpheres != null) { - Gizmos.color = Color.yellow; - for (int i = 0; i < m_PositioningSpheres.Length; ++i) { - Gizmos.DrawWireSphere(transform.TransformPoint(m_PositioningSpheres[i]), - m_ScaledPositioningSphereRadius); - } - } - if (WidgetSibling != null) { - Gizmos.color = Color.red; - Gizmos.DrawWireSphere(transform.position, WidgetSibling.m_CollisionRadius); - } - } - /**/ - } -} // namespace TiltBrush +// Copyright 2020 The Tilt Brush Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// 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 UnityEngine; +using UnityEngine.Localization; +using UnityEngine.Localization.Settings; +using TMPro; + +namespace TiltBrush +{ + + [System.Serializable] + public struct PopupMapKey + { + public GameObject m_PopUpPrefab; + public SketchControlsScript.GlobalCommands m_Command; + } + + public class BasePanel : MonoBehaviour + { + static private float GAZE_DISTANCE = 10 * App.METERS_TO_UNITS; + static private float LARGE_DISTANCE = 9999.0f * App.METERS_TO_UNITS; + + // Types etc + + protected class TextSpring + { + public float m_CurrentAngle; + public float m_DesiredAngle; + public float m_Velocity; + + public void Update(float fK, float fDampen) + { + float fToDesired = m_DesiredAngle - m_CurrentAngle; + fToDesired *= fK; + float fDampenedVel = m_Velocity * fDampen; + float fSpringForce = fToDesired - fDampenedVel; + m_Velocity += fSpringForce; + m_CurrentAngle += (m_Velocity * Time.deltaTime); + } + } + + protected enum DescriptionState + { + Open, + Closing, + Closed + } + + protected enum PanelState + { + Unused, + Unavailable, + Available, + } + + // These names are used in our player prefs, so they must be protected from obfuscation + // Do not change the names of any of them, unless they've never been released. + [Serializable] + public enum PanelType + { + SketchSurface, + Color, + Brush, + AudioReactor, + AdminPanelMobile, + ToolsBasicMobile, + ToolsBasic, + Experimental, + ToolsAdvancedMobile, + MemoryWarning, + Labs, + Sketchbook, + SketchbookMobile, + BrushMobile, + AppSettings, + Tutorials, + Reference, + Lights, + GuideTools, + Environment, + Camera, + Testing, + Icosa, + BrushExperimental, + ToolsAdvanced, + AppSettingsMobile, + AdminPanel, + ExtraPanel, + ExtraMobile, + IcosaMobile, + LabsMobile, + ReferenceMobile, + CameraPath, + BrushLab, + WebcamPanel = 5200, + Scripts = 6000, + SnapSettings = 8000, + StencilSettings = 20200, + LayersPanel = 15000, + TransformPanel = 12000, + } + + private enum FixedTransitionState + { + Floating, + FixedToFloating, + FloatingToFixed, + Fixed + } + + // Inspector data, tunables + [SerializeField] protected PanelType m_PanelType; + + [SerializeField] protected Collider m_Collider; + [SerializeField] public GameObject m_Mesh; + [SerializeField] protected Renderer m_Border; + [SerializeField] protected Collider m_MeshCollider; + [SerializeField] protected Vector3 m_ParticleBounds; + + [SerializeField] protected PopupMapKey[] m_PanelPopUpMap; + [SerializeField] protected string m_PanelDescription; + [SerializeField] protected LocalizedString m_LocalizedPanelDescription; + + public string PanelDescription + { + get + { + try + { + var locString = m_LocalizedPanelDescription.GetLocalizedStringAsync().Result; + return locString; + } + catch + { + return m_PanelDescription; + } + } + } + + [SerializeField] protected GameObject m_PanelDescriptionPrefab; + + [SerializeField] protected Vector3 m_PanelDescriptionOffset; + [SerializeField] protected Color m_PanelDescriptionColor; + + [SerializeField] protected GameObject m_PanelFlairPrefab; + [SerializeField] protected Vector3 m_PanelFlairOffset; + + [SerializeField] protected float m_DescriptionSpringK = 4.0f; + [SerializeField] protected float m_DescriptionSpringDampen = 0.2f; + [SerializeField] protected float m_DescriptionClosedAngle = -90.0f; + [SerializeField] protected float m_DescriptionOpenAngle = 0.0f; + [SerializeField] protected float m_DescriptionAlphaDistance = 90.0f; + + [SerializeField] protected GameObject[] m_Decor; + + [SerializeField] protected float m_GazeHighlightScaleMultiplier = 1.2f; + + [SerializeField] private float m_BorderMeshWidth = 0.02f; + [SerializeField] private float m_BorderMeshAdvWidth = 0.01f; + + [SerializeField] public float m_PanelSensitivity = 0.1f; + [SerializeField] protected bool m_ClampToBounds = false; + [SerializeField] protected Vector3 m_ReticleBounds; + + [SerializeField] public float m_BorderSphereHighlightRadius; + [SerializeField] protected Vector2 m_PositioningSpheresBounds; + [SerializeField] protected float m_PositioningSphereRadius = 0.4f; + + [SerializeField] public bool m_UseGazeRotation = false; + [SerializeField] public float m_MaxGazeRotation = 20.0f; + [SerializeField] protected float m_GazeActivateSpeed = 8.0f; + + [SerializeField] public Vector3 m_InitialSpawnPos; + [SerializeField] public Vector3 m_InitialSpawnRotEulers; + + [SerializeField] public float m_WandAttachAngle; + [SerializeField] public float m_WandAttachYOffset; + [SerializeField] public float m_WandAttachHalfHeight; + [SerializeField] private bool m_BeginFixed; + [SerializeField] private bool m_CanBeFixedToWand = true; + [SerializeField] private bool m_CanBeDetachedFromWand = true; + + [SerializeField] private float m_PopUpGazeDuration = .2f; + + [SerializeField] protected MeshRenderer[] m_PromoBorders; + + protected const float m_SwipeThreshold = 0.4f; + protected Material m_BorderMaterial; + + // Public, mutable data + + [NonSerialized] public float m_SweetSpotDistance = 1.0f; + [NonSerialized] public bool m_Fixed; + [NonSerialized] public bool m_WandPrimedForAttach; + [NonSerialized] public float m_WandAttachRadiusAdjust; + [NonSerialized] public float m_WandAttachYOffset_Target; + // This is used to store the Y offset of a fixed panel at the point where the user begins + // interacting with a panelWidget. Storing this value allows modifications to the panes to be + // undone. When the user ends interaction, _Stable is updated to be the _Target. + [NonSerialized] public float m_WandAttachYOffset_Stable; + + // Internal data + + protected PopUpWindow m_ActivePopUp; + protected SketchControlsScript.GlobalCommands m_DelayedCommand; + protected int m_DelayedCommandParam; + protected int m_DelayedCommandParam2; + + protected GameObject m_PanelDescriptionObject; + protected Renderer m_PanelDescriptionRenderer; + protected TextMeshPro m_PanelDescriptionTextMeshPro; + + protected Vector3 m_BaseScale; + protected float m_AdjustedScale; + + protected TextSpring m_PanelDescriptionTextSpring; + protected TextSpring m_PanelFlairSpring; + protected PanelFlair m_PanelFlair; + + protected Vector3 m_ReticleOffset; + protected Vector3 m_Bounds; + protected Vector3 m_WorkingReticleBounds; + + protected DescriptionState m_PanelDescriptionState; + protected DescriptionState m_PanelFlairState; + protected float m_CloseAngleThreshold; + + protected PanelState m_CurrentState; + protected PanelState m_DesiredState; + protected bool m_GazeActive; + protected bool m_GazeWasActive; + protected bool m_GazeDescriptionsActive; + + protected bool m_InputValid; + protected bool m_EatInput; + protected Ray m_ReticleSelectionRay; + + protected float m_PositioningPercent; + + protected float m_MaxGazeOffsetDistance; + protected Vector3 m_GazeRotationAxis; + protected float m_GazeRotationAngle; + protected Quaternion m_GazeRotationAmount; + protected float m_GazeActivePercent; + + protected UIComponentManager m_UIComponentManager; + protected NonScaleChild m_NonScaleChild; // potentially null + + // Private + + private List m_DecorRenderers; + private List m_DecorTextMeshes; + + private float m_ScaledPositioningSphereRadius; + private float m_PositioningExtent; + private Vector3[] m_PositioningSpheres; + private Vector3[] m_PositioningSpheresTransformed; + + private Vector3 m_PositioningHome; + private float m_PositioningK = 0.5f; + private float m_PositioningDampen = 0.1f; + private float m_DepenetrationScalar = 200.0f; + private Vector3 m_PositioningVelocity; + + private Vector3 m_GazeHitPositionCurrent; + private Vector3 m_GazeHitPositionDesired; + private float m_GazeHitPositionSpeed = 10.0f; + + protected Vector2 m_SwipeRecentMotion = Vector2.zero; + + private FixedTransitionState m_TransitionState; + private TrTransform m_WandTransitionTarget; + private static float m_WandTransitionDuration = .25f; + private float m_WandTransitionPercent; // 0 = on wand, 1 = at target + private float m_WandAttachAdjustSpeed = 16.0f; + private float m_WandAttachYOffset_Initial; + private float m_WandAttachAngle_Initial; + private PanelWidget m_WidgetSibling; + + private GameObject m_TempPopUpCollider; + private float m_PopUpGazeTimer; + + private bool m_AdvancedModePanel; + private bool m_CurrentlyVisibleInAdvancedMode; + + // TODO: The following are just to track down an elusive NRE. Delete when we've figured + // it out. + private bool m_PanelInitializationStarted; + private bool m_PanelInitializationFinished; + private float m_PanelDescriptionCounter; + public Action m_OverrideControllerMaterial; + + // Accessors/properties + + public Vector3 GetBounds() { return m_Bounds; } + public float GetPositioningExtent() { return m_PositioningExtent; } + public bool IsAvailable() { return m_CurrentState != PanelState.Unavailable; } + public bool IsActive() { return m_GazeActive; } + public bool BeginFixed { get { return m_BeginFixed; } } + public void ClearBeginFixed() { m_BeginFixed = false; } + public bool CanBeDetached { get { return m_CanBeDetachedFromWand; } } + public bool IsInInitialPosition() + { + return m_WandAttachYOffset == m_WandAttachYOffset_Initial && + m_WandAttachAngle == m_WandAttachAngle_Initial; + } + public PanelWidget WidgetSibling { get { return m_WidgetSibling; } } + public bool AdvancedModePanel { get { return m_AdvancedModePanel; } } + public bool CurrentlyVisibleInAdvancedMode { get { return m_CurrentlyVisibleInAdvancedMode; } } + public Vector3 ParticleBounds { get { return m_ParticleBounds; } } + public PopUpWindow PanelPopUp { get { return m_ActivePopUp; } } + + public Color GetGazeColorFromActiveGazePercent() + { + PanelManager pm = PanelManager.m_Instance; + return Color.Lerp(pm.PanelHighlightInactiveColor, pm.PanelHighlightActiveColor, + m_GazeActivePercent); + } + + public PanelType Type + { + get { return m_PanelType; } + } + + public virtual bool ShouldRegister { get { return true; } } + + public void InitAdvancedFlag(bool advanced) + { + m_AdvancedModePanel = advanced; + m_CurrentlyVisibleInAdvancedMode = m_BeginFixed; + } + + public float PopUpOffset + { + get { return m_ActivePopUp ? m_ActivePopUp.GetPopUpForwardOffset() : 0; } + } + + virtual protected void CalculateBounds() + { + Vector3 vCurrentScale = transform.localScale; + m_Bounds = m_ReticleBounds; + m_Bounds.x *= vCurrentScale.x * 0.5f; + m_Bounds.y *= vCurrentScale.y * 0.5f; + m_Bounds.z = 0.0f; + + if (m_ActivePopUp == null) + { + m_WorkingReticleBounds = m_Bounds; + } + else + { + Vector3 vPopUpCurrentScale = m_ActivePopUp.transform.localScale; + m_WorkingReticleBounds = m_ActivePopUp.GetReticleBounds(); + m_WorkingReticleBounds.x *= vPopUpCurrentScale.x * 0.5f; + m_WorkingReticleBounds.y *= vPopUpCurrentScale.y * 0.5f; + } + } + + public void ActivatePromoBorder(bool activate) + { + if (m_WidgetSibling) + { + if (activate) + { + m_WidgetSibling.RemovePromoMeshesFromTintable(m_PromoBorders); + } + else + { + m_WidgetSibling.AddPromoMeshesToTintable(m_PromoBorders); + } + } + foreach (var m in m_PromoBorders) + { + m.material = activate ? PromoManager.m_Instance.SharePromoMaterial : m_BorderMaterial; + } + } + + virtual public void SetInIntroMode(bool inIntro) { } + + public void SetPositioningPercent(float fPercent) + { + m_PositioningPercent = fPercent; + } + + public void SetScale(float fScale) + { + m_AdjustedScale = fScale; + transform.localScale = m_BaseScale * m_AdjustedScale; + } + + public bool PanelIsUsed() { return m_CurrentState != PanelState.Unused; } + + public Collider GetCollider() { return m_Collider; } + + public bool HasMeshCollider() + { + return m_MeshCollider != null; + } + + virtual public bool RaycastAgainstMeshCollider(Ray rRay, out RaycastHit rHitInfo, float fDist) + { + rHitInfo = new RaycastHit(); + bool bReturnValue = false; + + // Creating a popup when a popup exists will generate a temp collider. This is to prevent + // forced, accidental out of bounds user input. + if (m_TempPopUpCollider != null) + { + BoxCollider tempCollider = m_TempPopUpCollider.GetComponent(); + bReturnValue = tempCollider.Raycast(rRay, out rHitInfo, fDist); + if (!bReturnValue) + { + // If we're ever not pointing at the temp collider, destroy it. + Destroy(m_TempPopUpCollider); + m_TempPopUpCollider = null; + } + } + + // If we've got a pop-up, check collision against that guy first. + if (m_ActivePopUp != null) + { + var collider = m_ActivePopUp.GetCollider(); + if (collider == null) { throw new InvalidOperationException("No popup collider"); } + bReturnValue = bReturnValue || + m_ActivePopUp.GetCollider().Raycast(rRay, out rHitInfo, fDist); + } + + // Check custom colliders on components. + bReturnValue = bReturnValue || + m_UIComponentManager.RaycastAgainstCustomColliders(rRay, out rHitInfo, fDist); + + // If we didn't have a pop-up, or collision failed, default to base mesh. + if (m_MeshCollider == null) { throw new InvalidOperationException("No mesh collider"); } + bReturnValue = bReturnValue || m_MeshCollider.Raycast(rRay, out rHitInfo, fDist); + return bReturnValue; + } + + virtual public void AssignControllerMaterials(InputManager.ControllerName controller) + { + m_UIComponentManager.AssignControllerMaterials(controller); + + // Allows components to override the regular controller material + // without worrying about execution order etc + if (m_OverrideControllerMaterial != null) + { + m_OverrideControllerMaterial(); + // Clear afterwards. This needs to be set every frame + m_OverrideControllerMaterial = null; + } + } + + /// This function is used to determine the value to be passed in to the controller pad mesh's + /// shader for visualizing swipes and other actions. + /// It is called by SketchControls when the panel is in focus. + public float GetControllerPadShaderRatio(InputManager.ControllerName controller) + { + return m_UIComponentManager.GetControllerPadShaderRatio(controller); + } + + public bool BrushPadAnimatesOnHover() + { + return m_UIComponentManager.BrushPadAnimatesOnAnyHover(); + } + + public bool UndoRedoBlocked() + { + // This function could be generalized to allow specific UIComponents to block undo/redo, + // but we only need it in a single case right now, so it's a bit more specific. + return m_ActivePopUp == null ? false : m_ActivePopUp.BlockUndoRedo(); + } + + virtual public void OnPanelMoved() { } + + virtual protected void Awake() + { + m_WandAttachYOffset_Initial = m_WandAttachYOffset; + m_WandAttachAngle_Initial = m_WandAttachAngle; + m_WandAttachYOffset_Target = m_WandAttachYOffset; + } + + // Happens at App Start() time. + virtual public void InitPanel() + { + m_PanelInitializationStarted = true; + m_BorderMaterial = m_Border.material; + m_BaseScale = transform.localScale; + m_AdjustedScale = 1.0f; + + CalculateBounds(); + m_NonScaleChild = GetComponent(); + + if (m_PanelDescriptionPrefab != null) + { + m_PanelDescriptionObject = (GameObject)Instantiate(m_PanelDescriptionPrefab); + m_PanelDescriptionObject.transform.position = m_Mesh.transform.position; + m_PanelDescriptionObject.transform.rotation = m_Mesh.transform.rotation; + m_PanelDescriptionObject.transform.SetParent(transform); + Vector3 vScale = m_PanelDescriptionObject.transform.localScale; + vScale *= transform.localScale.x; + m_PanelDescriptionObject.transform.localScale = vScale; + + m_PanelDescriptionRenderer = m_PanelDescriptionObject.GetComponent(); + if (m_PanelDescriptionRenderer) + { + m_PanelDescriptionRenderer.enabled = false; + } + + m_PanelDescriptionTextMeshPro = m_PanelDescriptionObject.GetComponent(); + if (m_PanelDescriptionTextMeshPro) + { + m_PanelDescriptionTextMeshPro.text = PanelDescription; + m_PanelDescriptionTextMeshPro.color = m_PanelDescriptionColor; + } + LocalizationSettings.SelectedLocaleChanged += OnSelectedLocaleChanged; + } + + if (m_PanelFlairPrefab != null) + { + GameObject go = (GameObject)Instantiate(m_PanelFlairPrefab); + m_PanelFlair = go.GetComponent(); + m_PanelFlair.ParentToPanel(transform, m_PanelFlairOffset); + } + + m_PanelDescriptionState = DescriptionState.Closing; + m_PanelFlairState = DescriptionState.Closing; + + m_CloseAngleThreshold = Mathf.Abs(m_DescriptionOpenAngle - m_DescriptionClosedAngle) * 0.01f; + + m_PanelDescriptionTextSpring = new TextSpring(); + m_PanelDescriptionTextSpring.m_CurrentAngle = m_DescriptionClosedAngle; + m_PanelDescriptionTextSpring.m_DesiredAngle = m_DescriptionClosedAngle; + m_PanelFlairSpring = new TextSpring(); + m_PanelFlairSpring.m_CurrentAngle = m_DescriptionClosedAngle; + m_PanelFlairSpring.m_DesiredAngle = m_DescriptionClosedAngle; + + PanelManager pm = PanelManager.m_Instance; + m_Border.material.SetColor("_Color", pm.PanelHighlightInactiveColor); + + m_DecorRenderers = new List(); + m_DecorTextMeshes = new List(); + + if (m_Decor.Length > 0) + { + // Cache all decor renderers. + for (int i = 0; i < m_Decor.Length; ++i) + { + Renderer[] aChildRenderers = m_Decor[i].GetComponentsInChildren(); + for (int j = 0; j < aChildRenderers.Length; ++j) + { + // Prefer to cache a text mesh pro object if we find one. + TextMeshPro tmp = aChildRenderers[j].GetComponent(); + if (tmp) + { + m_DecorTextMeshes.Add(tmp); + } + else + { + // Otherwise, the standard renderer will do. + m_DecorRenderers.Add(aChildRenderers[j]); + m_DecorRenderers[m_DecorRenderers.Count - 1].material.SetColor("_Color", + pm.PanelHighlightInactiveColor); + } + } + } + } + + m_CurrentState = PanelState.Available; + m_DesiredState = PanelState.Available; + m_GazeActive = false; + m_PositioningPercent = 0.0f; + + if (m_PositioningSpheresBounds.x > 0.0f && m_PositioningSpheresBounds.y > 0.0f && m_PositioningSphereRadius > 0.0f) + { + Vector2 vSphereBounds = m_PositioningSpheresBounds; + vSphereBounds.x -= m_PositioningSphereRadius * 0.5f; + vSphereBounds.y -= m_PositioningSphereRadius * 0.5f; + m_ScaledPositioningSphereRadius = m_PositioningSphereRadius * transform.localScale.x; + + int iNumSpheresWidth = Mathf.CeilToInt((vSphereBounds.x * 2.0f) / m_PositioningSphereRadius); + int iNumSpheresHeight = Mathf.CeilToInt((vSphereBounds.y * 2.0f) / m_PositioningSphereRadius); + int iTotalNumSpheres = (iNumSpheresWidth * 2) + ((iNumSpheresHeight - 2) * 2); + m_PositioningSpheres = new Vector3[iTotalNumSpheres]; + + float fXInterval = (vSphereBounds.x / (float)(iNumSpheresWidth - 1)) * 2.0f; + float fYInterval = (vSphereBounds.y / (float)(iNumSpheresHeight - 1)) * 2.0f; + for (int i = 0; i < iNumSpheresWidth; ++i) + { + float fX = -vSphereBounds.x + (fXInterval * (float)i); + m_PositioningSpheres[i].Set(fX, -vSphereBounds.y, 0.0f); + } + for (int i = 0; i < iNumSpheresHeight - 2; ++i) + { + float fY = -vSphereBounds.y + (fYInterval * (float)(i + 1)); + m_PositioningSpheres[iNumSpheresWidth + (i * 2)].Set(-vSphereBounds.x, fY, 0.0f); + m_PositioningSpheres[iNumSpheresWidth + (i * 2) + 1].Set(vSphereBounds.x, fY, 0.0f); + } + for (int i = iTotalNumSpheres - iNumSpheresWidth; i < iTotalNumSpheres; ++i) + { + int iIndex = i - (iTotalNumSpheres - iNumSpheresWidth); + float fX = -vSphereBounds.x + (fXInterval * (float)iIndex); + m_PositioningSpheres[i].Set(fX, vSphereBounds.y, 0.0f); + } + + m_PositioningSpheresTransformed = new Vector3[m_PositioningSpheres.Length]; + for (int i = 0; i < m_PositioningSpheresTransformed.Length; ++i) + { + m_PositioningSpheresTransformed[i] = new Vector3(); + m_PositioningExtent = Mathf.Max(m_PositioningExtent, Mathf.Max(m_PositioningSpheres[i].x, m_PositioningSpheres[i].y)); + } + m_PositioningExtent += (m_PositioningSphereRadius * 2.0f); + } + + m_MaxGazeOffsetDistance = m_Bounds.magnitude; + m_GazeRotationAmount = Quaternion.identity; + + m_UIComponentManager = GetComponent(); + m_UIComponentManager.SetColor(pm.PanelHighlightInactiveColor); + + m_WidgetSibling = GetComponent(); + if (m_Fixed) + { + m_TransitionState = FixedTransitionState.Fixed; + } + + // Bake border meshs. + float width = !m_AdvancedModePanel ? m_BorderMeshAdvWidth : m_BorderMeshWidth; + Color baseCol = !m_AdvancedModePanel ? pm.PanelBorderMeshOutlineColor : pm.PanelBorderMeshBaseColor; + Color outlineCol = !m_AdvancedModePanel ? pm.PanelBorderMeshBaseColor : pm.PanelBorderMeshOutlineColor; + BakedMeshOutline[] bakeries = GetComponentsInChildren(true); + BakedMeshOutline borderBakery = m_Border.GetComponent(); + for (int i = 0; i < bakeries.Length; ++i) + { + if (bakeries[i] == borderBakery) + { + // The border is the only bakery that gets custom treatment. + bakeries[i].Bake(baseCol, outlineCol, width); + } + else + { + bakeries[i].Bake(pm.PanelBorderMeshBaseColor, pm.PanelBorderMeshOutlineColor, m_BorderMeshWidth); + } + } + + m_PanelInitializationFinished = true; + } + + public void CloseActivePopUp(bool force) + { + if (m_ActivePopUp != null) + { + if (m_ActivePopUp.RequestClose(force)) + { + InvalidateIfActivePopup(m_ActivePopUp); + } + } + } + + public void VerifyStateForFloating() + { + m_TransitionState = FixedTransitionState.Floating; + m_WandTransitionPercent = 1; + } + + public void SetPanelStableToTarget() + { + m_WandAttachYOffset_Stable = m_WandAttachYOffset_Target; + } + + public void ResetPanelToInitialPosition() + { + m_WandAttachYOffset = m_WandAttachYOffset_Initial; + m_WandAttachYOffset_Target = m_WandAttachYOffset_Initial; + m_WandAttachYOffset_Stable = m_WandAttachYOffset_Initial; + m_WandAttachAngle = m_WandAttachAngle_Initial; + + if (m_TransitionState != FixedTransitionState.Fixed) + { + m_Fixed = true; + m_TransitionState = FixedTransitionState.Fixed; + m_WandTransitionPercent = 0; + } + } + + public void ResetPanel() + { + // Get rid of the popup as fast as possible. + if (m_ActivePopUp != null) + { + Destroy(m_ActivePopUp.gameObject); + InvalidateIfActivePopup(m_ActivePopUp); + } + Destroy(m_TempPopUpCollider); + m_TempPopUpCollider = null; + + //reset gaze animations + m_PanelDescriptionState = DescriptionState.Closed; + if (m_PanelDescriptionRenderer) + { + m_PanelDescriptionRenderer.enabled = false; + } + + m_PanelFlairState = DescriptionState.Closed; + if (m_PanelFlair != null) + { + m_PanelFlair.Hide(); + } + + UpdatePanelColor(PanelManager.m_Instance.PanelHighlightInactiveColor); + + m_GazeActive = false; + m_GazeActivePercent = 0.0001f; + m_GazeRotationAxis = Vector3.zero; + } + + public void InvalidateIfActivePopup(PopUpWindow activePopup) + { + // If this popup isn't the active one, don't bother. + if (activePopup == m_ActivePopUp) + { + m_ActivePopUp = null; + // Eat input when we close a popup so the close action doesn't carry over. + m_EatInput = true; + } + } + + private void OnSelectedLocaleChanged(Locale locale) + { + if (m_PanelDescriptionTextMeshPro) + { + m_PanelDescriptionTextMeshPro.text = PanelDescription; + } + } + + private void OnDestroy() + { + LocalizationSettings.SelectedLocaleChanged -= OnSelectedLocaleChanged; + } + + void OnEnable() + { + OnEnablePanel(); + } + + void OnDisable() + { + OnDisablePanel(); + } + + virtual protected void OnEnablePanel() + { + if (PanelManager.m_Instance != null) + { + if (PanelManager.m_Instance.AdvancedModeActive()) + { + m_CurrentlyVisibleInAdvancedMode = true; + } + } + } + + virtual protected void OnDisablePanel() + { + if (PanelManager.m_Instance != null) + { + if (PanelManager.m_Instance.AdvancedModeActive()) + { + m_CurrentlyVisibleInAdvancedMode = false; + } + } + } + + public void ResetReticleOffset() + { + m_ReticleOffset = Vector3.zero; + } + + public void UpdateReticleOffset(float fXDelta, float fYDelta) + { + m_ReticleOffset.x += fXDelta * m_PanelSensitivity; + m_ReticleOffset.y += fYDelta * m_PanelSensitivity; + + if (m_ClampToBounds) + { + m_ReticleOffset.x = Mathf.Clamp(m_ReticleOffset.x, -m_WorkingReticleBounds.x, m_WorkingReticleBounds.x); + m_ReticleOffset.y = Mathf.Clamp(m_ReticleOffset.y, -m_WorkingReticleBounds.y, m_WorkingReticleBounds.y); + m_ReticleOffset.z = m_WorkingReticleBounds.z; + } + } + + // Given a position that has been proven to be a hit point on the panel's collider and the cast + // direction that resulted in that point, determine where the reticle should be located. + // Used by wand panel method of interacting with panels. + virtual public void GetReticleTransformFromPosDir(Vector3 vInPos, Vector3 vInDir, out Vector3 vOutPos, out Vector3 vForward) + { + //by default, the collision point is ok, and the reticle's forward should be the same as the mesh + vOutPos = vInPos; + vForward = -m_Mesh.transform.forward; + + Vector3 dir = Vector3.forward; + Ray rCastRay = new Ray(vInPos - vInDir * 0.5f, vInDir); + + // If we have a ghost popup, collide with that to find our position. + if (m_TempPopUpCollider != null) + { + RaycastHit rHitInfo; + if (DoesRayHitCollider(rCastRay, m_TempPopUpCollider.GetComponent(), out rHitInfo)) + { + vOutPos = rHitInfo.point; + } + } + + // Override default and ghost with standard popup collision. + if (m_ActivePopUp != null) + { + m_ActivePopUp.CalculateReticleCollision(rCastRay, ref vOutPos, ref vForward); + } + else + { + // PopUps trump UIComponents, so if there isn't a PopUp, check against all UIComponents. + m_UIComponentManager.CalculateReticleCollision(rCastRay, ref vOutPos, ref vForward); + } + } + + // TODO : This is currently broken. Needs to be updated to use new + // m_UIComponentManager.CalculateReticleCollision style. + // Using m_ReticleOffset, determine where the reticle should be located. + // Used by gaze method of interacting with panels. + virtual public void GetReticleTransform(out Vector3 vPos, out Vector3 vForward, bool bGazeAndTap) + { + // For ViewingOnly controls, position the reticle at the gaze panel position + if (bGazeAndTap) + { + // Calculate plane intersection + Transform head = ViewpointScript.Head; + Ray ray = new Ray(head.position, head.forward); + RaycastHit rHitInfo; + if (RaycastAgainstMeshCollider(ray, out rHitInfo, GAZE_DISTANCE)) + { + vPos = rHitInfo.point; + } + else + { + vPos = new Vector3(LARGE_DISTANCE, LARGE_DISTANCE, LARGE_DISTANCE); + } + } + else + { + Vector3 vTransformedOffset = m_Mesh.transform.rotation * m_ReticleOffset; + vPos = transform.position + vTransformedOffset; + } + vForward = -m_Mesh.transform.forward; + } + + // This function should only be used when the app state changes in a way that requires + // an out-of-focus panel's visuals to become reflect a stale state. + virtual public void ForceUpdatePanelVisuals() + { + m_UIComponentManager.UpdateVisuals(); + } + + void Update() + { + BaseUpdate(); + } + + protected void BaseUpdate() + { + UpdateState(); + CalculateBounds(); + UpdateDescriptions(); + UpdateGazeBehavior(); + UpdateFixedTransition(); + } + + protected void UpdateState() + { + //check if we're switching activity + if (m_GazeWasActive != m_GazeActive) + { + if (m_GazeActive) + { + AudioManager.m_Instance.ActivatePanel(true, transform.position); + } + else + { + m_UIComponentManager.ResetInput(); + AudioManager.m_Instance.ActivatePanel(false, transform.position); + } + + m_GazeWasActive = m_GazeActive; + OnUpdateActive(); + } + + bool bGazeDescriptionsWereActive = m_GazeDescriptionsActive; + m_GazeDescriptionsActive = m_GazeActive; + + // Update components if gaze is active. + if (m_GazeDescriptionsActive) + { + m_UIComponentManager.UpdateVisuals(); + } + + //check if we're switching descriptions showing + if (bGazeDescriptionsWereActive != m_GazeDescriptionsActive) + { + if (m_GazeDescriptionsActive) + { + if (m_PanelDescriptionObject) + { + m_PanelDescriptionState = DescriptionState.Open; + m_PanelDescriptionTextSpring.m_DesiredAngle = m_DescriptionOpenAngle; + m_PanelDescriptionRenderer.enabled = true; + } + } + else + { + if (m_PanelDescriptionObject) + { + m_PanelDescriptionState = DescriptionState.Closing; + m_PanelDescriptionTextSpring.m_DesiredAngle = m_DescriptionClosedAngle; + ResetPanelFlair(); + } + m_UIComponentManager.ManagerLostFocus(); + m_UIComponentManager.Deactivate(); + if (m_ActivePopUp != null) + { + if (m_ActivePopUp.RequestClose()) + { + InvalidateIfActivePopup(m_ActivePopUp); + } + } + } + } + + //update state + m_CurrentState = m_DesiredState; + } + + virtual protected void OnUpdateActive() + { + } + + void UpdateMeshRotation() + { + m_Mesh.transform.rotation = m_GazeRotationAmount * transform.rotation; + } + + protected void UpdateDescriptions() + { + try + { + m_PanelDescriptionCounter = 0; + if (m_PanelDescriptionState != DescriptionState.Closed && m_PanelDescriptionObject != null) + { + m_PanelDescriptionCounter = 1; + m_PanelDescriptionTextSpring.Update(m_DescriptionSpringK, m_DescriptionSpringDampen); + + m_PanelDescriptionCounter = 2; + Quaternion qOrient = Quaternion.Euler(0.0f, m_PanelDescriptionTextSpring.m_CurrentAngle, 0.0f); + m_PanelDescriptionObject.transform.rotation = m_Mesh.transform.rotation * qOrient; + + m_PanelDescriptionCounter = 3; + Vector3 vPanelDescriptionOffset = m_Bounds; + vPanelDescriptionOffset.x *= m_PanelDescriptionOffset.x; + vPanelDescriptionOffset.y *= m_PanelDescriptionOffset.y; + Vector3 vTransformedOffset = m_Mesh.transform.rotation * vPanelDescriptionOffset; + m_PanelDescriptionObject.transform.position = m_Mesh.transform.position + vTransformedOffset; + + m_PanelDescriptionCounter = 4; + float fDistToClosed = Mathf.Abs(m_PanelDescriptionTextSpring.m_CurrentAngle - m_DescriptionClosedAngle); + Color descColor = m_PanelDescriptionColor; + if (m_ActivePopUp != null) + { + descColor = Color.Lerp(m_PanelDescriptionColor, + PanelManager.m_Instance.PanelHighlightInactiveColor, + m_ActivePopUp.GetTransitionRatioForVisuals()); + } + float fRatio = fDistToClosed / m_DescriptionAlphaDistance; + descColor.a = Mathf.Min(fRatio * fRatio, 1.0f); + if (m_PanelDescriptionTextMeshPro) + { + m_PanelDescriptionTextMeshPro.color = descColor; + } + + m_PanelDescriptionCounter = 5; + if (m_PanelDescriptionState == DescriptionState.Closing) + { + float fToDesired = m_PanelDescriptionTextSpring.m_DesiredAngle - m_PanelDescriptionTextSpring.m_CurrentAngle; + if (Mathf.Abs(fToDesired) <= m_CloseAngleThreshold) + { + m_PanelDescriptionRenderer.enabled = false; + m_PanelDescriptionState = DescriptionState.Closed; + } + } + } + + m_PanelDescriptionCounter = 6; + if (m_PanelFlairState != DescriptionState.Closed) + { + m_PanelDescriptionCounter = 7; + m_PanelFlairSpring.Update(m_DescriptionSpringK, m_DescriptionSpringDampen); + float fDistToClosed = Mathf.Abs(m_PanelFlairSpring.m_CurrentAngle - m_DescriptionClosedAngle); + float fRatio = fDistToClosed / m_DescriptionAlphaDistance; + float fAlpha = Mathf.Min(fRatio * fRatio, 1.0f); + + m_PanelDescriptionCounter = 8; + Quaternion qOrient = m_Mesh.transform.rotation * Quaternion.Euler(0.0f, m_PanelFlairSpring.m_CurrentAngle, 0.0f); + + m_PanelDescriptionCounter = 9; + if (m_PanelFlair != null) + { + m_PanelFlair.UpdateAnimationOnPanel(m_Bounds, qOrient, fAlpha); + } + + m_PanelDescriptionCounter = 10; + if (m_PanelFlairState == DescriptionState.Closing) + { + float fToDesired = m_PanelFlairSpring.m_DesiredAngle - m_PanelFlairSpring.m_CurrentAngle; + if (Mathf.Abs(fToDesired) <= m_CloseAngleThreshold) + { + if (m_PanelFlair != null) + { + m_PanelFlair.Hide(); + } + + m_PanelFlairState = DescriptionState.Closed; + } + } + } + } + catch (Exception ex) + { + string message = string.Format("{0}: Init State({1}, {2}), Counter({3})", + ex.Message, + m_PanelInitializationStarted, + m_PanelInitializationFinished, + m_PanelDescriptionCounter); + throw new Exception(message); + } + } + + protected virtual void UpdateGazeBehavior() + { + if (m_UseGazeRotation && m_Mesh) + { + float fPrevPercent = m_GazeActivePercent; + float fPercentStep = m_GazeActivateSpeed * Time.deltaTime; + if (IsActive()) + { + m_GazeActivePercent = Mathf.Min(m_GazeActivePercent + fPercentStep, 1.0f); + } + else + { + m_GazeActivePercent = Mathf.Max(m_GazeActivePercent - fPercentStep, 0.0f); + } + + //don't bother updating static panels + if (fPrevPercent > 0.0f) + { + float fRotationAngle = m_GazeRotationAngle * m_GazeActivePercent * (1.0f - m_PositioningPercent); + m_GazeRotationAmount = Quaternion.AngleAxis(fRotationAngle, m_GazeRotationAxis); + UpdateMeshRotation(); + + Color rPanelColor = GetGazeColor(); + if (m_Border.material == m_BorderMaterial) + { + m_Border.material.SetColor("_Color", rPanelColor); + } + + if (fPrevPercent < 1.0f) + { + float fScaleMult = m_GazeActivePercent * (m_GazeHighlightScaleMultiplier - 1.0f); + Vector3 newScale = m_BaseScale * m_AdjustedScale * (1.0f + fScaleMult); + if (m_NonScaleChild != null) + { + m_NonScaleChild.globalScale = newScale; + } + else + { + transform.localScale = newScale; + } + } + + UpdatePanelColor(rPanelColor); + m_UIComponentManager.GazeRatioChanged(m_GazeActivePercent); + } + } + } + + public Color GetGazeColor() + { + PanelManager pm = PanelManager.m_Instance; + Color targetColor = pm.PanelHighlightActiveColor; + if (m_ActivePopUp != null) + { + targetColor = Color.Lerp(pm.PanelHighlightActiveColor, + pm.PanelHighlightInactiveColor, + m_ActivePopUp.GetTransitionRatioForVisuals()); + } + + float t = m_GazeActivePercent; + if (SketchControlsScript.m_Instance.AtlasIconTextures) + { + // If we're atlasing panel textures, only send 0 and 1 through. + t = Mathf.Floor(m_GazeActivePercent + 0.5f); + } + return Color.Lerp(pm.PanelHighlightInactiveColor, targetColor, t); + } + + protected void UpdateFixedTransition() + { + // State machine for panel exploding off of wand controller. + if (m_TransitionState == FixedTransitionState.FixedToFloating) + { + m_WandTransitionPercent += Time.deltaTime / m_WandTransitionDuration; + if (m_WandTransitionPercent >= 1.0f) + { + m_WandTransitionPercent = 1.0f; + m_TransitionState = FixedTransitionState.Floating; + } + PanelManager.m_Instance.UpdateWandTransitionXf( + this, m_WandTransitionTarget, m_WandTransitionPercent); + } + else if (m_TransitionState == FixedTransitionState.FloatingToFixed) + { + m_WandTransitionPercent -= Time.deltaTime / m_WandTransitionDuration; + if (m_WandTransitionPercent <= 0.0f) + { + m_WandTransitionPercent = 0.0f; + m_TransitionState = FixedTransitionState.Fixed; + } + PanelManager.m_Instance.UpdateWandTransitionXf( + this, m_WandTransitionTarget, m_WandTransitionPercent); + } + else if (WidgetSibling && + WidgetSibling.IsUserInteracting(InputManager.ControllerName.Brush)) + { + // If the user is interacting with this panel, lock to a pane if this panel allows it. + if (m_CanBeFixedToWand) + { + PanelManager.m_Instance.AttachHeldPanelToWand(this); + } + } + else if (m_TransitionState == FixedTransitionState.Fixed) + { + // Update attach height. + float fStep = m_WandAttachAdjustSpeed * Time.deltaTime; + float fToTarget = m_WandAttachYOffset_Target - m_WandAttachYOffset; + if (Mathf.Abs(fToTarget) < fStep) + { + m_WandAttachYOffset = m_WandAttachYOffset_Target; + } + else + { + m_WandAttachYOffset += fStep * Mathf.Sign(fToTarget); + } + m_WandAttachRadiusAdjust = 0.0f; + } + } + + public void WidgetSiblingBeginInteraction() + { + PanelManager.m_Instance.InitPanesForPanelAttach(m_Fixed); + + // Initialize primed flag to off-- it'll get enabled if the attachment checks are valid. + m_WandPrimedForAttach = false; + + if (m_Fixed) + { + m_Fixed = false; + m_TransitionState = FixedTransitionState.Floating; + m_WandTransitionPercent = 1; + } + } + + public void WidgetSiblingEndInteraction() + { + if (!m_Fixed) + { + PanelManager.m_Instance.ResetPaneVisuals(); + if (m_WandPrimedForAttach || !CanBeDetached) + { + m_Fixed = true; + m_TransitionState = FixedTransitionState.Fixed; + m_WandTransitionPercent = 0; + } + + if (!m_WandPrimedForAttach) + { + // If we're releasing this panel and it's not snapping to a pane, make sure the pane + // panels are reset back to their stable positions. + PanelManager.m_Instance.SetFixedPanelsToStableOffsets(); + } + else + { + // If this panel is snapping to a pane, update it's stable position so it's sorted + // correctly when we close the gaps. + SetPanelStableToTarget(); + } + m_WandTransitionTarget = TrTransform.FromTransform(transform); + WidgetSibling.SetActiveTintToShowError(false); + + PanelManager.m_Instance.ClosePanePanelGaps(); + } + } + + // Target is ignored if the panel is reattaching to the wand + public void TransitionToWand(bool bFixed, TrTransform target) + { + if (bFixed && m_TransitionState != FixedTransitionState.Fixed) + { + m_TransitionState = FixedTransitionState.FloatingToFixed; + } + else if (!bFixed && m_TransitionState != FixedTransitionState.Floating) + { + m_WandTransitionTarget = target; + m_TransitionState = FixedTransitionState.FixedToFloating; + } + } + + void UpdatePanelColor(Color rPanelColor) + { + // Set the appropriate dim value for all our UI components. + m_UIComponentManager.SetColor(rPanelColor); + + OnUpdateGazeBehavior(rPanelColor); + + for (int i = 0; i < m_DecorRenderers.Count; ++i) + { + m_DecorRenderers[i].material.SetColor("_Color", rPanelColor); + } + for (int i = 0; i < m_DecorTextMeshes.Count; ++i) + { + m_DecorTextMeshes[i].color = rPanelColor; + } + } + + virtual protected void OnUpdateGazeBehavior(Color rPanelColor) { } + + virtual public void PanelGazeActive(bool bActive) + { + m_GazeActive = bActive; + m_GazeHitPositionCurrent = transform.position; + m_UIComponentManager.ResetInput(); + } + + void SetPanelFlairText(string sText) + { + if (m_PanelFlair != null) + { + // Interpret any message as a good message. + if (m_PanelFlair.AlwaysShow) + { + m_PanelFlair.SetText(sText); + m_PanelFlair.Show(); + m_PanelFlairState = DescriptionState.Open; + m_PanelFlairSpring.m_DesiredAngle = m_DescriptionOpenAngle; + } + else + { + if (sText != null && !sText.Equals("")) + { + m_PanelFlair.SetText(sText); + m_PanelFlair.Show(); + m_PanelFlairState = DescriptionState.Open; + m_PanelFlairSpring.m_DesiredAngle = m_DescriptionOpenAngle; + } + else if (m_PanelFlairState != DescriptionState.Closed) + { + m_PanelFlairState = DescriptionState.Closing; + m_PanelFlairSpring.m_DesiredAngle = m_DescriptionClosedAngle; + } + } + } + } + + public void ResetPanelFlair() + { + if (m_PanelFlairState != DescriptionState.Closed) + { + m_PanelFlairState = DescriptionState.Closing; + m_PanelFlairSpring.m_DesiredAngle = m_DescriptionClosedAngle; + } + } + + virtual public void OnWidgetShowAnimStart() { } + + virtual public void OnWidgetShowAnimComplete() { } + + virtual public void OnWidgetHide() { } + + /// Accumulates dpad input, and returns nonzero for a discrete swipe action. + /// Return value is 1 for "backward" swipe moving a page forward + /// and -1 for "forward" swipe moving a page backward. + protected int AccumulateSwipe() + { + int direction = 0; + if (InputManager.m_Instance.IsBrushScrollActive()) + { + // If our delta is beyond our trigger threshold, report it. + float fDelta = InputManager.m_Instance.GetAdjustedBrushScrollAmount(); + if (IncrementMotionAndCheckForSwipe(fDelta)) + { + direction = (int)Mathf.Sign(m_SwipeRecentMotion.x) * -1; + m_SwipeRecentMotion.x = 0.0f; + } + } + else + { + m_SwipeRecentMotion.x = 0.0f; + } + + return direction; + } + + /// Virtual so panels can interpret m_SwipeRecentMotion however they'd like. + virtual public bool IncrementMotionAndCheckForSwipe(float fMotion) + { + m_SwipeRecentMotion.x += fMotion; + return Mathf.Abs(m_SwipeRecentMotion.x) > m_SwipeThreshold; + } + + /// Panels are updated by SketchControls when they have focus. + public void UpdatePanel(Vector3 vToPanel, Vector3 vHitPoint) + { + // Validate input and cache it for this update. + m_InputValid = InputManager.m_Instance.GetCommand(InputManager.SketchCommands.Activate); + if (m_EatInput) + { + m_EatInput = m_InputValid; + m_InputValid = false; + } + + // Cache input ray for this update. + Vector3 vReticlePos = SketchControlsScript.m_Instance.GetUIReticlePos(); + m_ReticleSelectionRay = new Ray(vReticlePos - transform.forward, transform.forward); + + if (m_ActivePopUp != null) + { + var collider = m_ActivePopUp.GetCollider(); + if (collider == null) { throw new InvalidOperationException("No popup collider"); } + RaycastHit hitInfo; + + // If we're pointing at a popup, increment our gaze timer. + if (BasePanel.DoesRayHitCollider(m_ReticleSelectionRay, + m_ActivePopUp.GetCollider(), out hitInfo)) + { + if (m_ActivePopUp.IsOpen()) + { + m_PopUpGazeTimer += Time.deltaTime; + } + } + else if (!m_ActivePopUp.InputObjectHasFocus() && + (InputManager.m_Instance.GetCommandDown(InputManager.SketchCommands.Activate) || + m_PopUpGazeTimer > m_PopUpGazeDuration)) + { + // If we're not pointing at the popup and the user doesn't have focus on an element + // of the popup, dismiss the popup if we've pointed at it before, or there's input. + m_ActivePopUp.RequestClose(); + } + } + + if (m_UseGazeRotation) + { + m_GazeHitPositionDesired = vHitPoint; + Vector3 vCurrToDesired = m_GazeHitPositionDesired - m_GazeHitPositionCurrent; + float fStep = m_GazeHitPositionSpeed * Time.deltaTime; + if (vCurrToDesired.sqrMagnitude < fStep * fStep) + { + m_GazeHitPositionCurrent = m_GazeHitPositionDesired; + } + else + { + vCurrToDesired.Normalize(); + vCurrToDesired *= fStep; + m_GazeHitPositionCurrent += vCurrToDesired; + } + + Vector3 vToCenter = m_GazeHitPositionCurrent - GetCollider().transform.position; + float fOffsetDist = vToCenter.magnitude; + vToCenter.Normalize(); + m_GazeRotationAxis = Vector3.Cross(-vToPanel, vToCenter); + m_GazeRotationAxis.Normalize(); + m_GazeRotationAngle = (fOffsetDist / m_MaxGazeOffsetDistance) * m_MaxGazeRotation; + } + + // Update custom logic for panel. + OnUpdatePanel(vToPanel, vHitPoint); + + // Update UIComponents, with PopUps taking priority. + if (m_ActivePopUp) + { + if (!m_EatInput && m_PopUpGazeTimer > 0) + { + m_ActivePopUp.UpdateUIComponents(m_ReticleSelectionRay, m_InputValid, m_ActivePopUp.GetCollider()); + } + } + else + { + // TODO : I'm not convinced the 3rd parameter here should be the main collider. + // I think it might need to be the mesh collider. If so, the collider is only used in + // monoscopic mode and should be renamed appropriately. + m_UIComponentManager.UpdateUIComponents(m_ReticleSelectionRay, m_InputValid, GetCollider()); + + // If a popup was just spawned, clear our active UI component, as input will now be + // directed to the popup. + if (m_ActivePopUp) + { + m_UIComponentManager.ResetInput(); + } + + if (m_UIComponentManager.ActiveInputUIComponent == null) + { + SetPanelFlairText(null); + } + else + { + SetPanelFlairText(m_UIComponentManager.ActiveInputUIComponent.Description); + } + } + } + + /// Base level logic for updating panel. This should be called from any derived class. + virtual public void OnUpdatePanel(Vector3 vToPanel, Vector3 vHitPoint) { } + + public void InitForPanelMovement() + { + m_PositioningHome = transform.position; + m_PositioningVelocity.Set(0.0f, 0.0f, 0.0f); + m_WandAttachYOffset_Stable = m_WandAttachYOffset_Target; + } + + virtual public void PanelHasStoppedMoving() + { + m_GazeHitPositionCurrent = transform.position; + } + + public void CreatePopUp(SketchControlsScript.GlobalCommands rCommand, + int iCommandParam, int iCommandParam2, string sDelayedText = "", + Action delayedClose = null) + { + CreatePopUp(rCommand, iCommandParam, iCommandParam2, Vector3.zero, sDelayedText, delayedClose); + } + + public void CreatePopUp(SketchControlsScript.GlobalCommands rCommand, + int iCommandParam, int iCommandParam2, Vector3 vPopupOffset, string sDelayedText = "", + Action delayedClose = null) + { + bool bPopUpExisted = false; + Vector3 vPrevPopUpPos = Vector3.zero; + // If we've got an active popup, send it packing. + if (m_ActivePopUp != null) + { + // Create a copy of the collider so we don't pull the rug out from under the user. + m_TempPopUpCollider = m_ActivePopUp.DuplicateCollider(); + vPrevPopUpPos = m_ActivePopUp.transform.position; + CloseActivePopUp(false); + bPopUpExisted = true; + } + + if (m_ActivePopUp == null) + { + // Look for the appropriate popup for this command. + int iPopUpIndex = -1; + for (int i = 0; i < m_PanelPopUpMap.Length; ++i) + { + if (m_PanelPopUpMap[i].m_Command == rCommand) + { + iPopUpIndex = i; + break; + } + } + + if (iPopUpIndex >= 0) + { + Vector3 position = vPopupOffset; + CreatePopUp( + m_PanelPopUpMap[iPopUpIndex].m_PopUpPrefab, position, + bPopUpExisted, bPopUpExisted, iCommandParam, + iCommandParam2, rCommand, sDelayedText, delayedClose + ); + } + } + } + + public void CreatePopUp( + GameObject prefab, Vector3 position, + bool explicitPosition, bool transition, int iCommandParam = -1, int iCommandParam2 = -1, + SketchControlsScript.GlobalCommands delayedCommand = SketchControlsScript.GlobalCommands.Null, + string sDelayedText = "", Action delayedClose = null) + { + // Create a new popup. + GameObject popUp = Instantiate(prefab, + m_Mesh.transform.position, m_Mesh.transform.rotation); + m_ActivePopUp = popUp.GetComponent(); + + if (explicitPosition) + { + popUp.transform.position = position; + } + else + { + // Treat position as an offset + popUp.transform.position = m_Mesh.transform.position + + (m_Mesh.transform.forward * m_ActivePopUp.GetPopUpForwardOffset()) + + m_Mesh.transform.TransformVector(position); + } + + popUp.transform.parent = m_Mesh.transform; + m_ActivePopUp.Init(gameObject, sDelayedText); + m_ActivePopUp.SetPopupCommandParameters(iCommandParam, iCommandParam2); + + m_ActivePopUp.m_OnClose += delayedClose; + m_PopUpGazeTimer = 0; + m_EatInput = !m_ActivePopUp.IsLongPressPopUp(); + + // If we closed a popup to create this one, we wan't don't want the standard visual + // fade that happens when a popup comes in. We're spoofing the transition value + // for visuals to avoid a pop. + if (!transition) + { + m_ActivePopUp.SpoofTransitionValue(); + } + + // Cache the intended command. + m_DelayedCommand = delayedCommand; + m_DelayedCommandParam = iCommandParam; + m_DelayedCommandParam2 = iCommandParam2; + + } + + public void PositionPopUp(Vector3 basePos) + { + m_ActivePopUp.transform.position = basePos; + } + + public void ResolveDelayedButtonCommand(bool bConfirm, bool bKeepOpen = false) + { + PopUpWindow currentPopup = m_ActivePopUp; + if (bConfirm) + { + SketchControlsScript.m_Instance.IssueGlobalCommand( + m_DelayedCommand, m_DelayedCommandParam, m_DelayedCommandParam2); + } + // if the popup has changed since the start of the function (and it wasn't null at the start), + // that means that the global command called kicked off a new popup. In which case we shouldn't + // close the popup, or overwrite the delayed command. + bool panelChanged = (currentPopup != null) && (m_ActivePopUp != currentPopup); + if (!panelChanged) + { + m_DelayedCommand = SketchControlsScript.GlobalCommands.Null; + m_DelayedCommandParam = -1; + m_DelayedCommandParam2 = -1; + if (m_ActivePopUp != null && !bKeepOpen) + { + m_ActivePopUp.RequestClose(); + } + } + } + + virtual public void GotoPage(int iIndex) + { + } + + virtual public void AdvancePage(int iAmount) + { + } + + public void InitForCollisionDetection() + { + for (int i = 0; i < m_PositioningSpheresTransformed.Length; ++i) + { + m_PositioningSpheresTransformed[i] = transform.TransformPoint(m_PositioningSpheres[i]); + } + } + + public void CalculateDepenetration(BasePanel rOther) + { + Vector3 vThemToUs = transform.position - rOther.transform.position; + Vector3 vThemToUsNorm = vThemToUs.normalized; + float fMaxExtent = m_PositioningExtent + rOther.GetPositioningExtent(); + + if (vThemToUs.sqrMagnitude < fMaxExtent * fMaxExtent) + { + float fCombinedSphereRad = m_ScaledPositioningSphereRadius + rOther.m_ScaledPositioningSphereRadius; + float fCombinedSphereRadSq = fCombinedSphereRad * fCombinedSphereRad; + for (int i = 0; i < m_PositioningSpheresTransformed.Length; ++i) + { + for (int j = 0; j < rOther.m_PositioningSpheresTransformed.Length; ++j) + { + Vector3 vSphereToSphere = rOther.m_PositioningSpheresTransformed[j] - m_PositioningSpheresTransformed[i]; + if (vSphereToSphere.sqrMagnitude < fCombinedSphereRadSq) + { + float fSphereToSphereDist = vSphereToSphere.magnitude; + float fDepenetrationAmount = fCombinedSphereRad - fSphereToSphereDist; + m_PositioningVelocity += (vThemToUsNorm * fDepenetrationAmount * m_DepenetrationScalar * Time.deltaTime); + } + } + } + } + } + + public void CalculateDepenetration(Vector3 vOtherPos, float fCombinedRadius) + { + Vector3 vThemToUs = transform.position - vOtherPos; + if (vThemToUs.sqrMagnitude < fCombinedRadius * fCombinedRadius) + { + float fDepenetrationAmount = fCombinedRadius - vThemToUs.magnitude; + m_PositioningVelocity += (vThemToUs.normalized * fDepenetrationAmount * + m_DepenetrationScalar * Time.fixedDeltaTime); + } + } + + public void UpdatePositioningForces() + { + //use spring to bring us home + Vector3 vToHome = m_PositioningHome - transform.position; + vToHome *= m_PositioningK; + Vector3 vDampenedVel = m_PositioningVelocity * m_PositioningDampen; + Vector3 vSpringForce = vToHome - vDampenedVel; + m_PositioningVelocity += vSpringForce; + + //update position + Vector3 vPos = transform.position; + vPos += (m_PositioningVelocity * Time.deltaTime); + transform.position = vPos; + if (m_NonScaleChild) + { + m_NonScaleChild.OnPosRotChanged(); + } + } + + /// Update the delayed command parameter that is used when a popup confirmation button is pressed. + /// This can be used when something provides more context to the initial command. + public void UpdateDelayedCommandParameter(int newParam) + { + m_DelayedCommandParam = newParam; + } + + static public bool DoesRayHitCollider(Ray rRay, Collider rCollider, bool skipAngleCheck = false) + { + if (!skipAngleCheck && Vector3.Angle(rRay.direction, rCollider.transform.forward) > 90.0f) + { + return false; + } + + RaycastHit rHitInfo; + return rCollider.Raycast(rRay, out rHitInfo, 100.0f); + } + + static public bool DoesRayHitCollider(Ray rRay, Collider rCollider, out RaycastHit rHitInfo) + { + return rCollider.Raycast(rRay, out rHitInfo, 100.0f); + } + + /* + * For Debugging. + * + void OnDrawGizmos() { + if (m_PositioningSpheres != null) { + Gizmos.color = Color.yellow; + for (int i = 0; i < m_PositioningSpheres.Length; ++i) { + Gizmos.DrawWireSphere(transform.TransformPoint(m_PositioningSpheres[i]), + m_ScaledPositioningSphereRadius); + } + } + if (WidgetSibling != null) { + Gizmos.color = Color.red; + Gizmos.DrawWireSphere(transform.position, WidgetSibling.m_CollisionRadius); + } + } + /**/ + } +} // namespace TiltBrush diff --git a/Assets/Scripts/GUI/IcosaLoginKeyboardController.cs b/Assets/Scripts/GUI/IcosaLoginKeyboardController.cs new file mode 100644 index 0000000000..d2a6cf2256 --- /dev/null +++ b/Assets/Scripts/GUI/IcosaLoginKeyboardController.cs @@ -0,0 +1,59 @@ +// Copyright 2023 The Open Brush Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// 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 UnityEngine; +using UnityEngine.Events; + +namespace TiltBrush +{ + public class IcosaLoginKeyboardController : MonoBehaviour + { + private KeyboardUI m_KeyboardUI; + [NonSerialized] public static string m_InitialText; + public UnityEvent OnSubmit; + public bool InputEnabled = true; + + void Awake() + { + m_KeyboardUI = GetComponentInChildren(includeInactive: true); + m_KeyboardUI.KeyPressed += KeyPressed; + m_KeyboardUI.AddConsoleContent(m_InitialText); + InputEnabled = true; + } + + private void OnDestroy() + { + m_KeyboardUI.KeyPressed -= KeyPressed; + } + + private void KeyPressed(object sender, KeyboardKeyEventArgs e) + { + if (!e.IsPress) return; // Ignore key up events + switch (e.Key.KeyType) + { + case KeyboardKeyType.Enter: + InputEnabled = false; // Prevents double submit + OnSubmit.Invoke(m_KeyboardUI.ConsoleContent); + break; + } + } + + public void Clear() + { + m_KeyboardUI.Clear(); + } + } +} // namespace TiltBrush diff --git a/Assets/Scripts/GUI/IcosaLoginKeyboardController.cs.meta b/Assets/Scripts/GUI/IcosaLoginKeyboardController.cs.meta new file mode 100644 index 0000000000..b59edf3665 --- /dev/null +++ b/Assets/Scripts/GUI/IcosaLoginKeyboardController.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 16e24e82bd0c4dcbb02c41882fb95f45 +timeCreated: 1699388418 \ No newline at end of file diff --git a/Assets/Scripts/GUI/PolyModelButton.cs b/Assets/Scripts/GUI/IcosaModelButton.cs similarity index 74% rename from Assets/Scripts/GUI/PolyModelButton.cs rename to Assets/Scripts/GUI/IcosaModelButton.cs index bb3633c084..8f9985d049 100644 --- a/Assets/Scripts/GUI/PolyModelButton.cs +++ b/Assets/Scripts/GUI/IcosaModelButton.cs @@ -1,195 +1,195 @@ -// Copyright 2020 The Tilt Brush Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// 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.Collections; -using UnityEngine; - -namespace TiltBrush -{ - - public class PolyModelButton : ModelButton - { - [SerializeField] private GameObject m_LoadingOverlay; - - private PolyAssetCatalog.AssetDetails m_PacAsset; - - public PolyAssetCatalog.AssetDetails Asset - { - get { return m_PacAsset; } - } - - protected override Texture2D UnloadedTexture - { - get - { - if (m_PacAsset.Thumbnail == null) - { - return base.UnloadedTexture; - } - else - { - return m_PacAsset.Thumbnail; - } - } - } - - protected override string ModelName - { - get { return m_PacAsset.HumanName; } - } - - public override bool IsAvailable() - { - return base.IsAvailable() && m_PacAsset != null && - (!App.PolyAssetCatalog.IsLoading(m_PacAsset.AssetId)); - } - - public void SetPreset(PolyAssetCatalog.AssetDetails asset, int index) - { - if (asset != m_PacAsset) - { - m_LoadingOverlay.SetActive(false); - } - m_PacAsset = asset; - SetPreset(asset.Model, index); - - if (m_PacAsset.ModelRotation != null) - { - Quaternion publishedRotation = m_PacAsset.ModelRotation.Value; - m_PreviewBaseRotation = Quaternion.Euler(0, publishedRotation.eulerAngles.y, 0); - } - } - - override protected void RequestModelPreloadInternal(string reason) - { - App.PolyAssetCatalog.RequestModelLoad(m_PacAsset.AssetId, reason); - m_LoadingOverlay.SetActive(true); - } - - override protected void CancelRequestModelPreload() - { - if (m_PacAsset == null) { return; } - var pac = App.PolyAssetCatalog; - var assetId = m_PacAsset.AssetId; - pac.CancelRequestModelLoad(assetId); - m_LoadingOverlay.SetActive(pac.IsLoading(assetId)); - } - - protected override void OnButtonPressed() - { - // Early out if this model had errors loading. - if (m_Model != null && m_Model.Error != null) - { - return; - } - StartCoroutine(SpawnModelCoroutine("button")); - } - - // Emits user-visible error on failure - protected IEnumerator SpawnModelCoroutine(string reason) - { - if (m_Model == null) - { - // Same as calling Model.RequestModelPreload -> RequestModelLoadInternal, except - // this won't ignore the request if the load-into-memory previously failed. - App.PolyAssetCatalog.RequestModelLoad(m_PacAsset.AssetId, reason); - m_LoadingOverlay.SetActive(true); - } - // It is possible from this section forward that the user may have moved on to a different page - // on the Poly panel, which is why we use a local copy of 'model' rather than m_Model. - string assetId = m_PacAsset.AssetId; - Model model; - // A model in the catalog will become non-null once the gltf has been downloaded or is in the - // cache. - while ((model = App.PolyAssetCatalog.GetModel(assetId)) == null) - { - yield return null; - } - // We only want to disable the loading overlay if the button is still referring to the same - // asset. - if (assetId == m_PacAsset.AssetId) - { - m_LoadingOverlay.SetActive(false); - } - - // A model becomes valid once the gltf has been successfully read into a Unity mesh. - if (!model.m_Valid) - { - // The model might be in the "loaded with error" state, but it seems harmless to try again. - // If the user keeps clicking, we'll keep trying. - yield return model.LoadFullyCoroutine(reason); - Debug.Assert(model.m_Valid || model.Error != null); - } - - if (!model.m_Valid) - { - // TODO: Is there a reason not to do this unconditionally? - if (assetId == m_PacAsset.AssetId) - { - RefreshModelButton(); - } - OutputWindowScript.Error($"Couldn't load model: {model.Error?.message}", model.Error?.detail); - } - else - { - SpawnValidModel(model); - } - } - - protected override void RefreshModelButton() - { - base.RefreshModelButton(); - if (m_Model != null) - { - if (m_Model.m_Valid) - { - m_LoadingOverlay.SetActive(false); - SetButtonTexture(m_PacAsset.Thumbnail, 1); - } - else if (m_Model.Error != null) - { - m_LoadingOverlay.SetActive(false); - } - } - } - - override public string UnloadedExtraDescription() - { - PolyPanel polyp = m_Manager.GetComponent(); - Debug.AssertFormat(polyp, "PolyModelButton should be a child of the PolyPanel"); - return (polyp && polyp.ShowingUser) ? null : m_PacAsset.AccountName; - } - - override public string LoadedExtraDescription() - { - return UnloadedExtraDescription(); - } - - public override void UpdateButtonState(bool bActivateInputValid) - { - base.UpdateButtonState(bActivateInputValid); - if (IsHover()) - { - m_PreviewParent.localScale = Vector3.one; - } - } - - public override void ResetState() - { - base.ResetState(); - m_PreviewParent.localScale = Vector3.zero; - } - } - -} // namespace TiltBrush +// Copyright 2020 The Tilt Brush Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// 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.Collections; +using UnityEngine; + +namespace TiltBrush +{ + + public class IcosaModelButton : ModelButton + { + [SerializeField] private GameObject m_LoadingOverlay; + + private IcosaAssetCatalog.AssetDetails m_IcosaAsset; + + public IcosaAssetCatalog.AssetDetails Asset + { + get { return m_IcosaAsset; } + } + + protected override Texture2D UnloadedTexture + { + get + { + if (m_IcosaAsset.Thumbnail == null) + { + return base.UnloadedTexture; + } + else + { + return m_IcosaAsset.Thumbnail; + } + } + } + + protected override string ModelName + { + get { return m_IcosaAsset.HumanName; } + } + + public override bool IsAvailable() + { + return base.IsAvailable() && m_IcosaAsset != null && + (!App.IcosaAssetCatalog.IsLoading(m_IcosaAsset.AssetId)); + } + + public void SetPreset(IcosaAssetCatalog.AssetDetails asset, int index) + { + if (asset != m_IcosaAsset) + { + m_LoadingOverlay.SetActive(false); + } + m_IcosaAsset = asset; + SetPreset(asset.Model, index); + + if (m_IcosaAsset.ModelRotation != null) + { + Quaternion publishedRotation = m_IcosaAsset.ModelRotation.Value; + m_PreviewBaseRotation = Quaternion.Euler(0, publishedRotation.eulerAngles.y, 0); + } + } + + override protected void RequestModelPreloadInternal(string reason) + { + App.IcosaAssetCatalog.RequestModelLoad(m_IcosaAsset.AssetId, reason); + m_LoadingOverlay.SetActive(true); + } + + override protected void CancelRequestModelPreload() + { + if (m_IcosaAsset == null) { return; } + var pac = App.IcosaAssetCatalog; + var assetId = m_IcosaAsset.AssetId; + pac.CancelRequestModelLoad(assetId); + m_LoadingOverlay.SetActive(pac.IsLoading(assetId)); + } + + protected override void OnButtonPressed() + { + // Early out if this model had errors loading. + if (m_Model != null && m_Model.Error != null) + { + return; + } + StartCoroutine(SpawnModelCoroutine("button")); + } + + // Emits user-visible error on failure + protected IEnumerator SpawnModelCoroutine(string reason) + { + if (m_Model == null) + { + // Same as calling Model.RequestModelPreload -> RequestModelLoadInternal, except + // this won't ignore the request if the load-into-memory previously failed. + App.IcosaAssetCatalog.RequestModelLoad(m_IcosaAsset.AssetId, reason); + m_LoadingOverlay.SetActive(true); + } + // It is possible from this section forward that the user may have moved on to a different page + // on the Poly panel, which is why we use a local copy of 'model' rather than m_Model. + string assetId = m_IcosaAsset.AssetId; + Model model; + // A model in the catalog will become non-null once the gltf has been downloaded or is in the + // cache. + while ((model = App.IcosaAssetCatalog.GetModel(assetId)) == null) + { + yield return null; + } + // We only want to disable the loading overlay if the button is still referring to the same + // asset. + if (assetId == m_IcosaAsset.AssetId) + { + m_LoadingOverlay.SetActive(false); + } + + // A model becomes valid once the gltf has been successfully read into a Unity mesh. + if (!model.m_Valid) + { + // The model might be in the "loaded with error" state, but it seems harmless to try again. + // If the user keeps clicking, we'll keep trying. + yield return model.LoadFullyCoroutine(reason); + Debug.Assert(model.m_Valid || model.Error != null); + } + + if (!model.m_Valid) + { + // TODO: Is there a reason not to do this unconditionally? + if (assetId == m_IcosaAsset.AssetId) + { + RefreshModelButton(); + } + OutputWindowScript.Error($"Couldn't load model: {model.Error?.message}", model.Error?.detail); + } + else + { + SpawnValidModel(model); + } + } + + protected override void RefreshModelButton() + { + base.RefreshModelButton(); + if (m_Model != null) + { + if (m_Model.m_Valid) + { + m_LoadingOverlay.SetActive(false); + SetButtonTexture(m_IcosaAsset.Thumbnail, 1); + } + else if (m_Model.Error != null) + { + m_LoadingOverlay.SetActive(false); + } + } + } + + override public string UnloadedExtraDescription() + { + IcosaPanel polyp = m_Manager.GetComponent(); + Debug.AssertFormat(polyp, "PolyModelButton should be a child of the PolyPanel"); + return (polyp && polyp.ShowingUser) ? null : m_IcosaAsset.AccountName; + } + + override public string LoadedExtraDescription() + { + return UnloadedExtraDescription(); + } + + public override void UpdateButtonState(bool bActivateInputValid) + { + base.UpdateButtonState(bActivateInputValid); + if (IsHover()) + { + m_PreviewParent.localScale = Vector3.one; + } + } + + public override void ResetState() + { + base.ResetState(); + m_PreviewParent.localScale = Vector3.zero; + } + } + +} // namespace TiltBrush diff --git a/Assets/Scripts/GUI/PolyModelButton.cs.meta b/Assets/Scripts/GUI/IcosaModelButton.cs.meta similarity index 100% rename from Assets/Scripts/GUI/PolyModelButton.cs.meta rename to Assets/Scripts/GUI/IcosaModelButton.cs.meta diff --git a/Assets/Scripts/GUI/PolyPanel.cs b/Assets/Scripts/GUI/IcosaPanel.cs similarity index 78% rename from Assets/Scripts/GUI/PolyPanel.cs rename to Assets/Scripts/GUI/IcosaPanel.cs index 238aafda11..8f65164fca 100644 --- a/Assets/Scripts/GUI/PolyPanel.cs +++ b/Assets/Scripts/GUI/IcosaPanel.cs @@ -1,309 +1,310 @@ -// Copyright 2020 The Tilt Brush Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// 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 UnityEngine.Localization; -using TMPro; - -namespace TiltBrush -{ - - public enum PolySetType - { - User, - Liked, - Featured - } - - public class PolyPanel : ModalPanel - { - [SerializeField] private TextMeshPro m_PanelText; - [SerializeField] private TextMeshPro m_PanelTextSubtitle; - [SerializeField] private TextMeshPro m_PanelTextUserSubtitle; - [SerializeField] private LocalizedString m_PanelTextStandard; - public string PanelTextStandard { get { return m_PanelTextStandard.GetLocalizedStringAsync().Result; } } - [SerializeField] private LocalizedString m_PanelTextFeatured; - public string PanelTextFeatured { get { return m_PanelTextFeatured.GetLocalizedStringAsync().Result; } } - [SerializeField] private LocalizedString m_PanelTextLiked; // Liked Models - public string PanelTextLiked { get { return m_PanelTextLiked.GetLocalizedStringAsync().Result; } } - [SerializeField] private Renderer m_PolyGalleryRenderer; - [SerializeField] private GameObject m_NoObjectsMessage; - [SerializeField] private GameObject m_InternetError; - [SerializeField] private GameObject m_NoAuthoredModelsMessage; - [SerializeField] private GameObject m_NoLikesMessage; - [SerializeField] private GameObject m_NotLoggedInMessage; - [SerializeField] private GameObject m_OutOfDateMessage; - [SerializeField] private GameObject m_NoPolyConnectionMessage; - - private PolySetType m_CurrentSet; - private bool m_LoggedIn; - - // State for automatically loading models. - int m_LastPageIndexForLoad = -1; - PolySetType m_LastSetTypeForLoad = PolySetType.User; - - public bool ShowingFeatured { get { return m_CurrentSet == PolySetType.Featured; } } - public bool ShowingLikes { get { return m_CurrentSet == PolySetType.Liked; } } - public bool ShowingUser { get { return m_CurrentSet == PolySetType.User; } } - - - - override public void OnWidgetShowAnimComplete() - { - SetVisiblePolySet(m_CurrentSet); - } - - public override void InitPanel() - { - base.InitPanel(); - - m_LoggedIn = App.GoogleIdentity.LoggedIn; - - m_NoObjectsMessage.SetActive(false); - m_InternetError.SetActive(false); - m_NoAuthoredModelsMessage.SetActive(false); - m_NoLikesMessage.SetActive(false); - m_NotLoggedInMessage.SetActive(false); - m_OutOfDateMessage.SetActive(false); - m_NoPolyConnectionMessage.SetActive(false); - } - - public override bool IsInButtonMode(ModeButton button) - { - var polySetButton = button as PolySetButton; - return polySetButton && polySetButton.m_ButtonType == m_CurrentSet; - } - - protected override void OnStart() - { - // Initialize icons. - PolyModelButton[] rPanelButtons = m_Mesh.GetComponentsInChildren(); - foreach (PolyModelButton icon in rPanelButtons) - { - GameObject go = icon.gameObject; - icon.SetButtonGrayscale(icon); - go.SetActive(false); - Icons.Add(icon); - } - - m_CurrentSet = PolySetType.Featured; - - // Make sure Poly gallery button starts at greyscale when panel is initialized - m_PolyGalleryRenderer.material.SetFloat("_Grayscale", 1); - - App.PolyAssetCatalog.RequestRefresh(m_CurrentSet); - App.PolyAssetCatalog.CatalogChanged += OnPolyAssetCatalogChanged; - } - - void SetVisiblePolySet(PolySetType type) - { - m_CurrentSet = type; - App.PolyAssetCatalog.RequestRefresh(m_CurrentSet); - ResetPageIndex(); - RefreshPage(); - } - - void OnPolyAssetCatalogChanged() - { - RefreshPage(); - } - - protected override void RefreshPage() - { - m_NoLikesMessage.SetActive(false); - m_NoAuthoredModelsMessage.SetActive(false); - m_NotLoggedInMessage.SetActive(false); - if (VrAssetService.m_Instance.NoConnection) - { - m_NoPolyConnectionMessage.SetActive(true); - RefreshPanelText(); - base.RefreshPage(); - return; - } - if (!VrAssetService.m_Instance.Available) - { - m_OutOfDateMessage.SetActive(true); - RefreshPanelText(); - base.RefreshPage(); - return; - } - - m_NumPages = ((App.PolyAssetCatalog.NumCloudModels(m_CurrentSet) - 1) / Icons.Count) + 1; - int numCloudModels = App.PolyAssetCatalog.NumCloudModels(m_CurrentSet); - - if (m_LastPageIndexForLoad != PageIndex || m_LastSetTypeForLoad != m_CurrentSet) - { - // Unload the previous page's models. - - // This function may be called multiple times as icons load, only unload the old models once, - // otherwise the current page's models will be thrashed. - m_LastPageIndexForLoad = PageIndex; - m_LastSetTypeForLoad = m_CurrentSet; - - // Destroy previews so only the thumbnail is visible. - for (int i = 0; i < Icons.Count; i++) - { - ((ModelButton)Icons[i]).DestroyModelPreview(); - } - - App.PolyAssetCatalog.UnloadUnusedModels(); - } - - for (int i = 0; i < Icons.Count; i++) - { - PolyModelButton icon = (PolyModelButton)Icons[i]; - // Set sketch index relative to page based index - int iMapIndex = m_IndexOffset + i; - - // Init icon according to availability of sketch - GameObject go = icon.gameObject; - if (iMapIndex < numCloudModels) - { - PolyAssetCatalog.AssetDetails asset = - App.PolyAssetCatalog.GetPolyAsset(m_CurrentSet, iMapIndex); - go.SetActive(true); - - if (icon.Asset != null && asset.AssetId != icon.Asset.AssetId) - { - icon.DestroyModelPreview(); - } - icon.SetPreset(asset, iMapIndex); - - // Note that App.UserConfig.Flags.PolyModelPreload falls through to - // App.PlatformConfig.EnablePolyPreload if it isn't set in Tilt Brush.cfg. - if (App.UserConfig.Flags.PolyModelPreload) - { - icon.RequestModelPreload(PageIndex); - } - } - else - { - go.SetActive(false); - } - } - - bool internetError = - App.PolyAssetCatalog.NumCloudModels(PolySetType.Featured) == 0; - m_InternetError.SetActive(internetError); - - RefreshPanelText(); - switch (m_CurrentSet) - { - case PolySetType.User: - if (!internetError) - { - if (App.GoogleIdentity.LoggedIn) - { - if (numCloudModels == 0) - { - m_NoAuthoredModelsMessage.SetActive(true); - } - } - else - { - m_NotLoggedInMessage.SetActive(true); - } - } - break; - case PolySetType.Liked: - if (!internetError) - { - if (App.GoogleIdentity.LoggedIn) - { - if (numCloudModels == 0) - { - m_NoLikesMessage.SetActive(true); - } - } - else - { - m_NotLoggedInMessage.SetActive(true); - } - } - break; - } - - base.RefreshPage(); - } - - void RefreshPanelText() - { - switch (m_CurrentSet) - { - case PolySetType.User: - m_PanelText.text = PanelTextStandard; - m_PanelTextSubtitle.gameObject.SetActive(false); - m_PanelTextUserSubtitle.gameObject.SetActive(true); - break; - case PolySetType.Featured: - m_PanelText.text = PanelTextFeatured; - m_PanelTextSubtitle.gameObject.SetActive(false); - m_PanelTextUserSubtitle.gameObject.SetActive(false); - break; - case PolySetType.Liked: - m_PanelText.text = PanelTextLiked; - m_PanelTextSubtitle.gameObject.SetActive(true); - m_PanelTextUserSubtitle.gameObject.SetActive(false); - break; - } - } - - void Update() - { - BaseUpdate(); - - // Update share button's text. - bool loggedIn = App.GoogleIdentity.LoggedIn; - if (loggedIn != m_LoggedIn) - { - m_LoggedIn = loggedIn; - RefreshPage(); - } - - PageFlipUpdate(); - } - - override protected void OnUpdateActive() - { - // If we're not active, hide all our preview panels - if (!m_GazeActive) - { - m_PolyGalleryRenderer.material.SetFloat("_Grayscale", 1); - foreach (var baseButton in Icons) - { - PolyModelButton icon = (PolyModelButton)baseButton; - icon.ResetState(); - icon.SetButtonGrayscale(icon); - } - - } - else if (m_CurrentState == PanelState.Available) - { - m_PolyGalleryRenderer.material.SetFloat("_Grayscale", 0); - foreach (var baseButton in Icons) - { - PolyModelButton icon = (PolyModelButton)baseButton; - icon.SetButtonGrayscale(false); - } - } - } - - // Works specifically with PolySetButtons. - public void ButtonPressed(PolySetType rType) - { - SetVisiblePolySet(rType); - } - - } -} // namespace TiltBrush +// Copyright 2020 The Tilt Brush Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// 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 UnityEngine.Localization; +using TMPro; + +namespace TiltBrush +{ + + public enum IcosaSetType + { + User, + Liked, + Featured + } + + public class IcosaPanel : ModalPanel + { + [SerializeField] private TextMeshPro m_PanelText; + [SerializeField] private TextMeshPro m_PanelTextSubtitle; + [SerializeField] private TextMeshPro m_PanelTextUserSubtitle; + [SerializeField] private LocalizedString m_PanelTextStandard; + public string PanelTextStandard { get { return m_PanelTextStandard.GetLocalizedStringAsync().Result; } } + [SerializeField] private LocalizedString m_PanelTextFeatured; + public string PanelTextFeatured { get { return m_PanelTextFeatured.GetLocalizedStringAsync().Result; } } + [SerializeField] private LocalizedString m_PanelTextLiked; // Liked Models + public string PanelTextLiked { get { return m_PanelTextLiked.GetLocalizedStringAsync().Result; } } + [SerializeField] private Renderer m_PolyGalleryRenderer; + [SerializeField] private GameObject m_NoObjectsMessage; + [SerializeField] private GameObject m_InternetError; + [SerializeField] private GameObject m_NoAuthoredModelsMessage; + [SerializeField] private GameObject m_NoLikesMessage; + [SerializeField] private GameObject m_NotLoggedInMessage; + [SerializeField] private GameObject m_OutOfDateMessage; + [SerializeField] private GameObject m_NoPolyConnectionMessage; + + private IcosaSetType m_CurrentSet; + private bool m_LoggedIn; + + // State for automatically loading models. + int m_LastPageIndexForLoad = -1; + IcosaSetType m_LastSetTypeForLoad = IcosaSetType.User; + + public bool ShowingFeatured { get { return m_CurrentSet == IcosaSetType.Featured; } } + public bool ShowingLikes { get { return m_CurrentSet == IcosaSetType.Liked; } } + public bool ShowingUser { get { return m_CurrentSet == IcosaSetType.User; } } + + + + override public void OnWidgetShowAnimComplete() + { + SetVisiblePolySet(m_CurrentSet); + } + + public override void InitPanel() + { + base.InitPanel(); + + m_LoggedIn = App.IcosaIsLoggedIn; + + m_NoObjectsMessage.SetActive(false); + m_InternetError.SetActive(false); + m_NoAuthoredModelsMessage.SetActive(false); + m_NoLikesMessage.SetActive(false); + m_NotLoggedInMessage.SetActive(false); + m_OutOfDateMessage.SetActive(false); + m_NoPolyConnectionMessage.SetActive(false); + } + + public override bool IsInButtonMode(ModeButton button) + { + var polySetButton = button as IcosaSetButton; + return polySetButton && polySetButton.m_ButtonType == m_CurrentSet; + } + + protected override void OnStart() + { + // Initialize icons. + IcosaModelButton[] rPanelButtons = m_Mesh.GetComponentsInChildren(); + foreach (IcosaModelButton icon in rPanelButtons) + { + GameObject go = icon.gameObject; + icon.SetButtonGrayscale(icon); + go.SetActive(false); + Icons.Add(icon); + } + + m_CurrentSet = IcosaSetType.User; + + // Make sure Poly gallery button starts at greyscale when panel is initialized + m_PolyGalleryRenderer.material.SetFloat("_Grayscale", 1); + + App.IcosaAssetCatalog.RequestRefresh(m_CurrentSet); + App.IcosaAssetCatalog.CatalogChanged += OnIcosaAssetCatalogChanged; + } + + void SetVisiblePolySet(IcosaSetType type) + { + m_CurrentSet = type; + App.IcosaAssetCatalog.RequestRefresh(m_CurrentSet); + ResetPageIndex(); + RefreshPage(); + } + + void OnIcosaAssetCatalogChanged() + { + RefreshPage(); + } + + protected override void RefreshPage() + { + m_NoLikesMessage.SetActive(false); + m_NoAuthoredModelsMessage.SetActive(false); + m_NotLoggedInMessage.SetActive(false); + m_InternetError.SetActive(false); + if (VrAssetService.m_Instance.NoConnection) + { + m_NoPolyConnectionMessage.SetActive(true); + RefreshPanelText(); + base.RefreshPage(); + return; + } + if (!VrAssetService.m_Instance.Available) + { + m_OutOfDateMessage.SetActive(true); + RefreshPanelText(); + base.RefreshPage(); + return; + } + + m_NumPages = ((App.IcosaAssetCatalog.NumCloudModels(m_CurrentSet) - 1) / Icons.Count) + 1; + int numCloudModels = App.IcosaAssetCatalog.NumCloudModels(m_CurrentSet); + + if (m_LastPageIndexForLoad != PageIndex || m_LastSetTypeForLoad != m_CurrentSet) + { + // Unload the previous page's models. + + // This function may be called multiple times as icons load, only unload the old models once, + // otherwise the current page's models will be thrashed. + m_LastPageIndexForLoad = PageIndex; + m_LastSetTypeForLoad = m_CurrentSet; + + // Destroy previews so only the thumbnail is visible. + for (int i = 0; i < Icons.Count; i++) + { + ((ModelButton)Icons[i]).DestroyModelPreview(); + } + + App.IcosaAssetCatalog.UnloadUnusedModels(); + } + + for (int i = 0; i < Icons.Count; i++) + { + IcosaModelButton icon = (IcosaModelButton)Icons[i]; + // Set sketch index relative to page based index + int iMapIndex = m_IndexOffset + i; + + // Init icon according to availability of sketch + GameObject go = icon.gameObject; + if (iMapIndex < numCloudModels) + { + IcosaAssetCatalog.AssetDetails asset = + App.IcosaAssetCatalog.GetPolyAsset(m_CurrentSet, iMapIndex); + go.SetActive(true); + + if (icon.Asset != null && asset.AssetId != icon.Asset.AssetId) + { + icon.DestroyModelPreview(); + } + icon.SetPreset(asset, iMapIndex); + + // Note that App.UserConfig.Flags.PolyModelPreload falls through to + // App.PlatformConfig.EnablePolyPreload if it isn't set in Tilt Brush.cfg. + if (App.UserConfig.Flags.IcosaModelPreload) + { + icon.RequestModelPreload(PageIndex); + } + } + else + { + go.SetActive(false); + } + } + + // Use featured model count as a proxy for "icosa is working" + bool internetError = App.IcosaAssetCatalog.NumCloudModels(IcosaSetType.Featured) == 0; + m_InternetError.SetActive(internetError); + + RefreshPanelText(); + switch (m_CurrentSet) + { + case IcosaSetType.User: + if (!internetError) + { + if (App.IcosaIsLoggedIn) + { + if (numCloudModels == 0) + { + m_NoAuthoredModelsMessage.SetActive(true); + } + } + else + { + m_NotLoggedInMessage.SetActive(true); + } + } + break; + case IcosaSetType.Liked: + if (!internetError) + { + if (App.IcosaIsLoggedIn) + { + if (numCloudModels == 0) + { + m_NoLikesMessage.SetActive(true); + } + } + else + { + m_NotLoggedInMessage.SetActive(true); + } + } + break; + } + + base.RefreshPage(); + } + + void RefreshPanelText() + { + switch (m_CurrentSet) + { + case IcosaSetType.User: + m_PanelText.text = PanelTextStandard; + m_PanelTextSubtitle.gameObject.SetActive(false); + m_PanelTextUserSubtitle.gameObject.SetActive(true); + break; + case IcosaSetType.Featured: + m_PanelText.text = PanelTextFeatured; + m_PanelTextSubtitle.gameObject.SetActive(false); + m_PanelTextUserSubtitle.gameObject.SetActive(false); + break; + case IcosaSetType.Liked: + m_PanelText.text = PanelTextLiked; + m_PanelTextSubtitle.gameObject.SetActive(true); + m_PanelTextUserSubtitle.gameObject.SetActive(false); + break; + } + } + + void Update() + { + BaseUpdate(); + + // Update share button's text. + bool loggedIn = App.IcosaIsLoggedIn; + if (loggedIn != m_LoggedIn) + { + m_LoggedIn = loggedIn; + RefreshPage(); + } + + PageFlipUpdate(); + } + + override protected void OnUpdateActive() + { + // If we're not active, hide all our preview panels + if (!m_GazeActive) + { + m_PolyGalleryRenderer.material.SetFloat("_Grayscale", 1); + foreach (var baseButton in Icons) + { + IcosaModelButton icon = (IcosaModelButton)baseButton; + icon.ResetState(); + icon.SetButtonGrayscale(icon); + } + + } + else if (m_CurrentState == PanelState.Available) + { + m_PolyGalleryRenderer.material.SetFloat("_Grayscale", 0); + foreach (var baseButton in Icons) + { + IcosaModelButton icon = (IcosaModelButton)baseButton; + icon.SetButtonGrayscale(false); + } + } + } + + // Works specifically with PolySetButtons. + public void ButtonPressed(IcosaSetType rType) + { + SetVisiblePolySet(rType); + } + + } +} // namespace TiltBrush diff --git a/Assets/Scripts/GUI/PolyPanel.cs.meta b/Assets/Scripts/GUI/IcosaPanel.cs.meta similarity index 100% rename from Assets/Scripts/GUI/PolyPanel.cs.meta rename to Assets/Scripts/GUI/IcosaPanel.cs.meta diff --git a/Assets/Scripts/GUI/PolySetButton.cs b/Assets/Scripts/GUI/IcosaSetButton.cs similarity index 73% rename from Assets/Scripts/GUI/PolySetButton.cs rename to Assets/Scripts/GUI/IcosaSetButton.cs index 911b75abd1..9797c51b8d 100644 --- a/Assets/Scripts/GUI/PolySetButton.cs +++ b/Assets/Scripts/GUI/IcosaSetButton.cs @@ -1,31 +1,31 @@ -// Copyright 2020 The Tilt Brush Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// 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 TiltBrush -{ - - public class PolySetButton : ModeButton - { - public PolySetType m_ButtonType; - - override protected void OnButtonPressed() - { - PolyPanel polyp = m_Manager.GetComponent(); - if (polyp) - { - polyp.ButtonPressed(m_ButtonType); - } - } - } -} // namespace TiltBrush +// Copyright 2020 The Tilt Brush Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// 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 TiltBrush +{ + + public class IcosaSetButton : ModeButton + { + public IcosaSetType m_ButtonType; + + override protected void OnButtonPressed() + { + IcosaPanel icosaPanel = m_Manager.GetComponent(); + if (icosaPanel) + { + icosaPanel.ButtonPressed(m_ButtonType); + } + } + } +} // namespace TiltBrush diff --git a/Assets/Scripts/GUI/PolySetButton.cs.meta b/Assets/Scripts/GUI/IcosaSetButton.cs.meta similarity index 100% rename from Assets/Scripts/GUI/PolySetButton.cs.meta rename to Assets/Scripts/GUI/IcosaSetButton.cs.meta diff --git a/Assets/Scripts/GUI/KeyboardPopUpWindow.cs b/Assets/Scripts/GUI/KeyboardPopUpWindow.cs index 5297a6a5d0..0c32ad1aba 100644 --- a/Assets/Scripts/GUI/KeyboardPopUpWindow.cs +++ b/Assets/Scripts/GUI/KeyboardPopUpWindow.cs @@ -46,6 +46,7 @@ private void OnDestroy() private void KeyPressed(object sender, KeyboardKeyEventArgs e) { + if (!e.IsPress) return; // Ignore key up events switch (e.Key.KeyType) { case KeyboardKeyType.Enter: @@ -61,7 +62,7 @@ private void KeyPressed(object sender, KeyboardKeyEventArgs e) if (m_SanitizeFilename) { - m_KeyboardUI.SantizeFilename(); + m_KeyboardUI.SanitizeFilename(); } } } diff --git a/Assets/Scripts/GUI/ProfilePopUpWindow.cs b/Assets/Scripts/GUI/ProfilePopUpWindow.cs index 7ee55dec97..d2684a7679 100644 --- a/Assets/Scripts/GUI/ProfilePopUpWindow.cs +++ b/Assets/Scripts/GUI/ProfilePopUpWindow.cs @@ -1,254 +1,417 @@ -// Copyright 2020 The Tilt Brush Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// 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 TMPro; - -namespace TiltBrush -{ - - public class ProfilePopUpWindow : OptionsPopUpWindow - { - public enum Mode - { - Accounts, - TakeOffHeadset, - GoogleHelp, - DriveHelp, - SketchfabHelp, - ConfirmLogin, - Unavailable, - } - - [SerializeField] private GameObject m_GoogleSignedInElements; - [SerializeField] private GameObject m_GoogleSignedOutElements; - [SerializeField] private GameObject m_GoogleConfirmSignOutElements; - [SerializeField] private GameObject m_SketchfabSignedInElements; - [SerializeField] private GameObject m_SketchfabSignedOutElements; - [SerializeField] private GameObject m_SketchfabConfirmSignOutElements; - [SerializeField] private Renderer m_GooglePhoto; - [SerializeField] private Renderer m_SketchfabPhoto; - [SerializeField] private TextMeshPro m_GoogleNameText; - [SerializeField] private TextMeshPro m_SketchfabNameText; - [SerializeField] private Texture2D m_GenericPhoto; - - [SerializeField] private GameObject m_Accounts; - [SerializeField] private GameObject m_TakeOffHeadset; - [SerializeField] private GameObject m_GoogleInfoElements; - [SerializeField] private GameObject m_DriveInfoElements; - [SerializeField] private GameObject m_SketchfabInfoElements; - [SerializeField] private GameObject m_UnavailableElements; - - [SerializeField] private GameObject m_DriveSyncEnabledElements; - [SerializeField] private GameObject m_DriveSyncDisabledElements; - [SerializeField] private GameObject m_DriveFullElements; - - [SerializeField] private GameObject m_DriveSyncIconEnabled; - [SerializeField] private GameObject m_DriveSyncIconDisabled; - [SerializeField] private GameObject m_DriveSyncIconDriveFull; - - [SerializeField] private GameObject m_BackupCompleteElements; - [SerializeField] private GameObject m_BackingUpElements; - [SerializeField] private TextMeshPro m_BackingUpProgress; - - [Header("Mobile State Members")] - [SerializeField] private GameObject m_ConfirmLoginElements; - [SerializeField] private SaveAndOptionButton m_SaveAndProceedButton; - - private Mode m_CurrentMode; - private bool m_DriveSyncing = false; - - private void Start() - { - App.DriveSync.SyncEnabledChanged += RefreshObjects; - } - - override public void Init(GameObject rParent, string sText) - { - base.Init(rParent, sText); - OAuth2Identity.ProfileUpdated += OnProfileUpdated; - RefreshObjects(); - App.DriveAccess.RefreshFreeSpaceAsync().AsAsyncVoid(); - - // TODO: Make configurable by secrets/login data available at runtime. - if (App.Config.DisableAccountLogins) - { - UpdateMode(Mode.Unavailable); - } - } - - void OnDestroy() - { - OAuth2Identity.ProfileUpdated -= OnProfileUpdated; - App.DriveSync.SyncEnabledChanged -= RefreshObjects; - } - - override protected void BaseUpdate() - { - base.BaseUpdate(); - if (App.DriveSync.Syncing != m_DriveSyncing) - { - RefreshObjects(); - } - RefreshBackupProgressText(); - } - - void RefreshObjects() - { - // Google. - bool driveFull = App.DriveSync.DriveIsLowOnSpace; - bool driveSyncEnabled = App.DriveSync.SyncEnabled; - bool driveSyncing = App.DriveSync.Syncing; - - OAuth2Identity.UserInfo googleInfo = App.GoogleIdentity.Profile; - bool googleInfoValid = googleInfo != null; - m_GoogleSignedInElements.SetActive(googleInfoValid); - m_GoogleSignedOutElements.SetActive(!googleInfoValid); - m_GoogleConfirmSignOutElements.SetActive(false); - if (googleInfoValid) - { - m_GoogleNameText.text = googleInfo.name; - m_GooglePhoto.material.mainTexture = googleInfo.icon; - - m_DriveSyncIconDriveFull.SetActive(driveFull && driveSyncEnabled); - m_DriveSyncIconEnabled.SetActive(!driveFull && driveSyncEnabled); - m_DriveSyncIconDisabled.SetActive(!driveSyncEnabled); - } - - // Sketchfab. - OAuth2Identity.UserInfo sketchfabInfo = App.SketchfabIdentity.Profile; - bool sketchfabInfoValid = sketchfabInfo != null; - m_SketchfabSignedInElements.SetActive(sketchfabInfoValid); - m_SketchfabSignedOutElements.SetActive(!sketchfabInfoValid); - m_SketchfabConfirmSignOutElements.SetActive(false); - if (sketchfabInfoValid) - { - m_SketchfabNameText.text = sketchfabInfo.name; - m_SketchfabPhoto.material.mainTexture = sketchfabInfo.icon; - } - - m_DriveFullElements.SetActive(driveFull && driveSyncEnabled); - m_DriveSyncEnabledElements.SetActive(!driveFull && driveSyncEnabled); - m_DriveSyncDisabledElements.SetActive(!driveSyncEnabled); - m_BackupCompleteElements.SetActive(!driveSyncing); - m_BackingUpElements.SetActive(driveSyncing); - m_DriveSyncing = driveSyncing; - RefreshBackupProgressText(); - } - - void RefreshBackupProgressText() - { - if (m_BackingUpElements.activeSelf) - { - m_BackingUpProgress.text = string.Format("Backing Up... {0}", - Mathf.Clamp(App.DriveSync.Progress, 0.01f, 0.99f).ToString("P0")); - } - } - - void UpdateMode(Mode newMode) - { - m_CurrentMode = newMode; - m_Accounts.SetActive(m_CurrentMode == Mode.Accounts); - m_TakeOffHeadset.SetActive(m_CurrentMode == Mode.TakeOffHeadset); - m_GoogleInfoElements.SetActive(m_CurrentMode == Mode.GoogleHelp); - m_DriveInfoElements.SetActive(m_CurrentMode == Mode.DriveHelp); - m_SketchfabInfoElements.SetActive(m_CurrentMode == Mode.SketchfabHelp); - m_UnavailableElements.SetActive(m_CurrentMode == Mode.Unavailable); - if (m_ConfirmLoginElements != null) - { - m_ConfirmLoginElements.SetActive(m_CurrentMode == Mode.ConfirmLogin); - } - // Reset persistent flag when switching modes. - m_Persistent = false; - } - - void OnProfileUpdated(OAuth2Identity _) - { - // If we're currently telling the user to take of the headset to signin, - // and they've done so correctly, switch back to the accounts view. - if (m_CurrentMode == Mode.TakeOffHeadset) - { - UpdateMode(Mode.Accounts); - } - RefreshObjects(); - } - - // This function serves as a callback from ProfilePopUpButtons that want to - // change the mode of the popup on click. - public void OnProfilePopUpButtonPressed(ProfilePopUpButton button) - { - switch (button.m_Command) - { - // Identifier for signaling we understand the info message. - case SketchControlsScript.GlobalCommands.Null: - case SketchControlsScript.GlobalCommands.GoogleDriveSync: - UpdateMode(Mode.Accounts); - RefreshObjects(); - break; - case SketchControlsScript.GlobalCommands.LoginToGenericCloud: - // m_CommandParam 1 is Google. m_CommandParam 2 is Sketchfab. - if (button.m_CommandParam == 1 || button.m_CommandParam == 2) - { - if (App.Config.IsMobileHardware && m_SaveAndProceedButton != null) - { - m_SaveAndProceedButton.SetCommandParameters(button.m_CommandParam, 0); - UpdateMode(Mode.ConfirmLogin); - } - else - { - OAuth2Identity.UserInfo userInfo = (button.m_CommandParam == 1) ? - App.GoogleIdentity.Profile : App.SketchfabIdentity.Profile; - if (userInfo == null) - { - UpdateMode(Mode.TakeOffHeadset); - m_Persistent = true; - } - } - } - break; - case SketchControlsScript.GlobalCommands.AccountInfo: - // Identifier for triggering an info message. - switch (button.m_CommandParam) - { - case 0: - UpdateMode(Mode.DriveHelp); - break; - case 1: - UpdateMode(Mode.GoogleHelp); - break; - case 2: - UpdateMode(Mode.SketchfabHelp); - break; - } - break; - case SketchControlsScript.GlobalCommands.SignOutConfirm: - switch ((Cloud)button.m_CommandParam) - { - case Cloud.Poly: - m_GoogleSignedInElements.SetActive(false); - m_GoogleSignedOutElements.SetActive(false); - m_GoogleConfirmSignOutElements.SetActive(true); - break; - case Cloud.Sketchfab: - m_SketchfabSignedInElements.SetActive(false); - m_SketchfabSignedOutElements.SetActive(false); - m_SketchfabConfirmSignOutElements.SetActive(true); - break; - case Cloud.None: break; - } - break; - } - } - } -} // namespace TiltBrush +// Copyright 2020 The Tilt Brush Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// 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; +using Org.OpenAPITools.Api; +using Org.OpenAPITools.Client; +using Org.OpenAPITools.Model; +using UnityEngine; +using TMPro; + +namespace TiltBrush +{ + + public class ProfilePopUpWindow : OptionsPopUpWindow + { + public enum Mode + { + Accounts, + TakeOffHeadset, + GoogleHelp, + DriveHelp, + SketchfabHelp, + IcosaHelp, + ConfirmLogin, + Unavailable, + } + + [SerializeField] private GameObject m_GoogleSignedInElements; + [SerializeField] private GameObject m_GoogleSignedOutElements; + [SerializeField] private GameObject m_GoogleConfirmSignOutElements; + [SerializeField] private GameObject m_SketchfabSignedInElements; + [SerializeField] private GameObject m_SketchfabSignedOutElements; + [SerializeField] private GameObject m_SketchfabConfirmSignOutElements; + [SerializeField] private GameObject m_IcosaSignedInElements; + [SerializeField] private GameObject m_IcosaSignedOutElements; + [SerializeField] private GameObject m_IcosaConfirmSignOutElements; + [SerializeField] private GameObject m_IcosaLoginElements; + [SerializeField] private Renderer m_GooglePhoto; + [SerializeField] private Renderer m_SketchfabPhoto; + [SerializeField] private Renderer m_IcosaPhoto; + [SerializeField] private TextMeshPro m_GoogleNameText; + [SerializeField] private TextMeshPro m_SketchfabNameText; + [SerializeField] private TextMeshPro m_IcosaNameText; + [SerializeField] private Texture2D m_GenericPhoto; + + [SerializeField] private GameObject m_Accounts; + [SerializeField] private GameObject m_TakeOffHeadset; + [SerializeField] private GameObject m_GoogleInfoElements; + [SerializeField] private GameObject m_DriveInfoElements; + [SerializeField] private GameObject m_SketchfabInfoElements; + [SerializeField] private GameObject m_IcosaInfoElements; + [SerializeField] private GameObject m_UnavailableElements; + [SerializeField] private GameObject m_DriveSyncEnabledElements; + [SerializeField] private GameObject m_DriveSyncDisabledElements; + [SerializeField] private GameObject m_DriveFullElements; + + [SerializeField] private GameObject m_DriveSyncIconEnabled; + [SerializeField] private GameObject m_DriveSyncIconDisabled; + [SerializeField] private GameObject m_DriveSyncIconDriveFull; + + [SerializeField] private GameObject m_BackupCompleteElements; + [SerializeField] private GameObject m_BackingUpElements; + [SerializeField] private TextMeshPro m_BackingUpProgress; + + [Header("Mobile State Members")] + [SerializeField] private GameObject m_ConfirmLoginElements; + [SerializeField] private SaveAndOptionButton m_SaveAndProceedButton; + + private Mode m_CurrentMode; + private bool m_DriveSyncing = false; + + private void Start() + { + App.DriveSync.SyncEnabledChanged += RefreshObjects; + } + + override public void Init(GameObject rParent, string sText) + { + base.Init(rParent, sText); + OAuth2Identity.ProfileUpdated += OnProfileUpdated; + RefreshObjects(); + m_IcosaLoginElements.SetActive(false); + if (App.IcosaIsLoggedIn) + { + StartCoroutine(FetchUserDataCoroutine(userData => + { + App.IcosaUserName = userData.Displayname; + App.IcosaUserId = userData.Id; + App.IcosaUserIcon = m_GenericPhoto; // TODO: Get icon from API + RefreshIcosaUserInfoUi(); + })); + } + + App.DriveAccess.RefreshFreeSpaceAsync().AsAsyncVoid(); + + // TODO: Make configurable by secrets/login data available at runtime. + if (App.Config.DisableAccountLogins) + { + UpdateMode(Mode.Unavailable); + } + } + + void OnDestroy() + { + OAuth2Identity.ProfileUpdated -= OnProfileUpdated; + App.DriveSync.SyncEnabledChanged -= RefreshObjects; + } + + override protected void BaseUpdate() + { + base.BaseUpdate(); + if (App.DriveSync.Syncing != m_DriveSyncing) + { + RefreshObjects(); + } + RefreshBackupProgressText(); + } + + void RefreshObjects() + { + // Google. + bool driveFull = App.DriveSync.DriveIsLowOnSpace; + bool driveSyncEnabled = App.DriveSync.SyncEnabled; + bool driveSyncing = App.DriveSync.Syncing; + + OAuth2Identity.UserInfo googleInfo = App.GoogleIdentity.Profile; + bool googleInfoValid = googleInfo != null; + m_GoogleSignedInElements.SetActive(googleInfoValid); + m_GoogleSignedOutElements.SetActive(!googleInfoValid); + m_GoogleConfirmSignOutElements.SetActive(false); + if (googleInfoValid) + { + m_GoogleNameText.text = googleInfo.name; + m_GooglePhoto.material.mainTexture = googleInfo.icon; + + m_DriveSyncIconDriveFull.SetActive(driveFull && driveSyncEnabled); + m_DriveSyncIconEnabled.SetActive(!driveFull && driveSyncEnabled); + m_DriveSyncIconDisabled.SetActive(!driveSyncEnabled); + } + + // Sketchfab. + OAuth2Identity.UserInfo sketchfabInfo = App.SketchfabIdentity.Profile; + bool sketchfabInfoValid = sketchfabInfo != null; + m_SketchfabSignedInElements.SetActive(sketchfabInfoValid); + m_SketchfabSignedOutElements.SetActive(!sketchfabInfoValid); + m_SketchfabConfirmSignOutElements.SetActive(false); + if (sketchfabInfoValid) + { + m_SketchfabNameText.text = sketchfabInfo.name; + m_SketchfabPhoto.material.mainTexture = sketchfabInfo.icon; + } + + // Icosa. + m_IcosaSignedInElements.SetActive(App.IcosaIsLoggedIn); + m_IcosaSignedOutElements.SetActive(!App.IcosaIsLoggedIn); + m_IcosaConfirmSignOutElements.SetActive(false); + RefreshIcosaUserInfoUi(); + + m_DriveFullElements.SetActive(driveFull && driveSyncEnabled); + m_DriveSyncEnabledElements.SetActive(!driveFull && driveSyncEnabled); + m_DriveSyncDisabledElements.SetActive(!driveSyncEnabled); + m_BackupCompleteElements.SetActive(!driveSyncing); + m_BackingUpElements.SetActive(driveSyncing); + m_DriveSyncing = driveSyncing; + RefreshBackupProgressText(); + } + + private void RefreshIcosaUserInfoUi() + { + m_IcosaNameText.text = App.IcosaUserName; + m_IcosaPhoto.material.mainTexture = App.IcosaUserIcon; + } + + public void HideIcosaLogin() + { + m_IcosaLoginElements.SetActive(false); + m_IcosaSignedInElements.SetActive(true); + m_IcosaSignedOutElements.SetActive(true); + m_SketchfabSignedOutElements.SetActive(true); + m_SketchfabSignedInElements.SetActive(true); + m_GoogleSignedInElements.SetActive(true); + m_GoogleSignedOutElements.SetActive(true); + m_Persistent = false; + RefreshObjects(); + } + + public void ShowIcosaLogin() + { + m_IcosaLoginElements.SetActive(true); + m_IcosaLoginElements.GetComponent().Clear(); + m_IcosaSignedInElements.SetActive(false); + m_IcosaSignedOutElements.SetActive(false); + m_SketchfabSignedOutElements.SetActive(false); + m_SketchfabSignedInElements.SetActive(false); + m_GoogleSignedInElements.SetActive(false); + m_GoogleSignedOutElements.SetActive(false); + } + + public void HandleIcosaLoginSubmit(string code) + { + if (App.IcosaIsLoggedIn) return; + StartCoroutine(LoginCoroutine(code)); + } + + private IEnumerator LoginCoroutine(string code) + { + var config = new Configuration(); + var loginApi = new LoginApi(VrAssetService.m_Instance.IcosaApiRoot); + config.BasePath = VrAssetService.m_Instance.IcosaApiRoot; + loginApi.Configuration = config; + var loginTask = loginApi.DeviceLoginLoginDeviceLoginPostAsync(code); + yield return new WaitUntil(() => loginTask.IsCompleted); + + if (loginTask.Exception != null) + { + if (loginTask.Exception.Message.Contains("401 Unauthorized")) + { + // TODO: Show error message. + LoginFailure(); + AudioManager.m_Instance.PlayTrashSound(transform.position); + } + yield break; + } + + if (loginTask.Result?.AccessToken == null) + { + // TODO: Show error message. + LoginFailure(); + AudioManager.m_Instance.PlayPinSound(transform.position, AudioManager.PinSoundType.Wobble); + yield break; + } + App.Instance.IcosaToken = loginTask.Result.AccessToken; + StartCoroutine(FetchUserDataCoroutine(userData => LoginSuccess(userData))); + } + + private IEnumerator FetchUserDataCoroutine(Action onSuccess) + { + var usersApi = new UsersApi(VrAssetService.m_Instance.IcosaApiRoot); + var config = new Configuration { AccessToken = App.Instance.IcosaToken }; + config.BasePath = VrAssetService.m_Instance.IcosaApiRoot; + usersApi.Configuration = config; + var getUserTask = usersApi.GetUsersMeUsersMeGetAsync(); + yield return new WaitUntil(() => getUserTask.IsCompleted); + + if (getUserTask.Exception != null) + { + if (getUserTask.Exception.Message.Contains("401 Unauthorized")) + { + // Clear user token + LoginFailure(); + } + Debug.Log($"GetUser failed with exception: {getUserTask.Exception}"); + yield break; + } + + var userData = getUserTask.Result; + if (userData == null) + { + Debug.Log($"Failure - no user data received"); + // TODO should we logout? Clear username/icon? + yield break; + } + onSuccess?.Invoke(userData); + } + + private void LoginSuccess(FullUser userData) + { + // Call the callback delegate if it's provided (which means this was called from the first coroutine) + App.IcosaUserName = userData.Displayname; + App.IcosaUserId = userData.Id; + App.IcosaUserIcon = m_GenericPhoto; // TODO: Get icon from API + RefreshIcosaUserInfoUi(); + HideIcosaLogin(); + } + + private void LoginFailure() + { + HideIcosaLogin(); + App.Instance.LogoutIcosa(); + } + + void RefreshBackupProgressText() + { + if (m_BackingUpElements.activeSelf) + { + m_BackingUpProgress.text = string.Format("Backing Up... {0}", + Mathf.Clamp(App.DriveSync.Progress, 0.01f, 0.99f).ToString("P0")); + } + } + + void UpdateMode(Mode newMode) + { + m_CurrentMode = newMode; + m_Accounts.SetActive(m_CurrentMode == Mode.Accounts); + m_TakeOffHeadset.SetActive(m_CurrentMode == Mode.TakeOffHeadset); + m_GoogleInfoElements.SetActive(m_CurrentMode == Mode.GoogleHelp); + m_DriveInfoElements.SetActive(m_CurrentMode == Mode.DriveHelp); + m_SketchfabInfoElements.SetActive(m_CurrentMode == Mode.SketchfabHelp); + m_IcosaInfoElements.SetActive(m_CurrentMode == Mode.IcosaHelp); + m_UnavailableElements.SetActive(m_CurrentMode == Mode.Unavailable); + if (m_ConfirmLoginElements != null) + { + m_ConfirmLoginElements.SetActive(m_CurrentMode == Mode.ConfirmLogin); + } + // Reset persistent flag when switching modes. + m_Persistent = false; + } + + void OnProfileUpdated(OAuth2Identity _) + { + // If we're currently telling the user to take of the headset to signin, + // and they've done so correctly, switch back to the accounts view. + if (m_CurrentMode == Mode.TakeOffHeadset) + { + Debug.Log($"OnProfileUpdated set AccountMode"); + UpdateMode(Mode.Accounts); + } + RefreshObjects(); + } + + // This function serves as a callback from ProfilePopUpButtons that want to + // change the mode of the popup on click. + public void OnProfilePopUpButtonPressed(ProfilePopUpButton button) + { + switch (button.m_Command) + { + // Identifier for signaling we understand the info message. + case SketchControlsScript.GlobalCommands.Null: + case SketchControlsScript.GlobalCommands.GoogleDriveSync: + UpdateMode(Mode.Accounts); + RefreshObjects(); + break; + case SketchControlsScript.GlobalCommands.LoginToGenericCloud: + // m_CommandParam 1 is Google. m_CommandParam 2 is Sketchfab. + if (button.m_CommandParam == 1 || button.m_CommandParam == 2) + { + if (App.Config.IsMobileHardware && m_SaveAndProceedButton != null) + { + m_SaveAndProceedButton.SetCommandParameters(button.m_CommandParam, 0); + UpdateMode(Mode.ConfirmLogin); + } + else + { + OAuth2Identity.UserInfo userInfo = (button.m_CommandParam == 1) ? + App.GoogleIdentity.Profile : App.SketchfabIdentity.Profile; + if (userInfo == null) + { + UpdateMode(Mode.TakeOffHeadset); + m_Persistent = true; + } + } + } + break; + case SketchControlsScript.GlobalCommands.LoginToIcosa: + if (!App.Config.IsMobileHardware) + { + OutputWindowScript.m_Instance.CreateInfoCardAtController( + InputManager.ControllerName.Brush, + SketchControlsScript.kRemoveHeadsetFyi, + fPopScalar: 0.5f + ); + } + + App.OpenURL($"{VrAssetService.m_Instance.IcosaHomePage}/device"); + ShowIcosaLogin(); + m_Persistent = true; + break; + case SketchControlsScript.GlobalCommands.AccountInfo: + // Identifier for triggering an info message. + switch (button.m_CommandParam) + { + case 0: + UpdateMode(Mode.DriveHelp); + break; + case 1: + UpdateMode(Mode.GoogleHelp); + break; + case 2: + UpdateMode(Mode.SketchfabHelp); + break; + case 3: + UpdateMode(Mode.IcosaHelp); + break; + } + break; + case SketchControlsScript.GlobalCommands.SignOutConfirm: + switch ((Cloud)button.m_CommandParam) + { + case Cloud.Sketchfab: + m_SketchfabSignedInElements.SetActive(false); + m_SketchfabSignedOutElements.SetActive(false); + m_SketchfabConfirmSignOutElements.SetActive(true); + break; + case Cloud.Icosa: + m_IcosaSignedInElements.SetActive(false); + m_IcosaSignedOutElements.SetActive(false); + m_IcosaConfirmSignOutElements.SetActive(true); + break; + case Cloud.None: break; + } + break; + } + } + } +} // namespace TiltBrush diff --git a/Assets/Scripts/GUI/SketchbookPanel.cs b/Assets/Scripts/GUI/SketchbookPanel.cs index 7f44fec2db..8b4224479a 100644 --- a/Assets/Scripts/GUI/SketchbookPanel.cs +++ b/Assets/Scripts/GUI/SketchbookPanel.cs @@ -1,794 +1,798 @@ -// Copyright 2020 The Tilt Brush Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// 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 UnityEngine.Localization; -using System; -using System.Collections.Generic; -using System.Linq; -using TMPro; - -namespace TiltBrush -{ - - public class SketchbookPanel : ModalPanel - { - // Index of the "local sketches" button in m_GalleryButtons - const int kElementNumberGalleryButtonLocal = 0; - // Amount of extra space to put below the "local sketches" gallery button - const float kGalleryButtonLocalPadding = .15f; - - [SerializeField] private Texture2D m_LoadingImageTexture; - [SerializeField] private Texture2D m_UnknownImageTexture; - [SerializeField] private TextMeshPro m_PanelTextPro; - [SerializeField] private LocalizedString m_PanelTextStandard; - public string PanelTextStandard { get { return m_PanelTextStandard.GetLocalizedStringAsync().Result; } } - [SerializeField] private LocalizedString m_PanelTextShowcase; - public string PanelTextShowcase { get { return m_PanelTextShowcase.GetLocalizedStringAsync().Result; } } - - [SerializeField] private LocalizedString m_PanelTextLiked; - public string PanelTextLiked { get { return m_PanelTextLiked.GetLocalizedStringAsync().Result; } } - [SerializeField] private LocalizedString m_PanelTextDrive; - public string PanelTextDrive { get { return m_PanelTextDrive.GetLocalizedStringAsync().Result; } } - [SerializeField] private GameObject m_NoSketchesMessage; - [SerializeField] private GameObject m_NoDriveSketchesMessage; - [SerializeField] private GameObject m_NoLikesMessage; - [SerializeField] private GameObject m_NotLoggedInMessage; - [SerializeField] private GameObject m_NotLoggedInDriveMessage; - [SerializeField] private GameObject m_NoShowcaseMessage; - [SerializeField] private GameObject m_ContactingServerMessage; - [SerializeField] private GameObject m_OutOfDateMessage; - [SerializeField] private GameObject m_NoPolyConnectionMessage; - [SerializeField] private Renderer m_OnlineGalleryButtonRenderer; - [SerializeField] private GameObject[] m_IconsOnFirstPage; - [SerializeField] private GameObject[] m_IconsOnNormalPage; - [SerializeField] private GameObject m_CloseButton; - [SerializeField] private GameObject m_NewSketchButton; - // Gallery buttons will automatically reposition based on how many are visible so they must be - // added to this array in order from top to bottom. - [SerializeField] private GalleryButton[] m_GalleryButtons; - [SerializeField] private int m_ElementNumberGalleryButtonDrive = 3; - [SerializeField] private float m_GalleryButtonHeight = 0.3186f; - [SerializeField] private Renderer m_ProfileButtonRenderer; - [SerializeField] private GameObject m_LoadingGallery; - [SerializeField] private GameObject m_DriveSyncProgress; - [SerializeField] private GameObject m_SyncingDriveIcon; - [SerializeField] private GameObject m_DriveEnabledIcon; - [SerializeField] private GameObject m_DriveDisabledIcon; - [SerializeField] private GameObject m_DriveFullIcon; - [SerializeField] private Vector2 m_SketchIconUvScale = new Vector2(0.7f, 0.7f); - [SerializeField] private Vector3 m_ReadOnlyPopupOffset; - - private float m_ImageAspect; - private Vector2 m_HalfInvUvScale; - - private SceneFileInfo m_FirstSketch; - - private bool m_AllIconTexturesAssigned; - private bool m_AllSketchesAreAvailable; - private SketchSetType m_CurrentSketchSet; - private SketchSet m_SketchSet; - private OptionButton m_NewSketchButtonScript; - private OptionButton m_PaintButtonScript; - private List m_IconScriptsOnFirstPage; - private List m_IconScriptsOnNormalPage; - private bool m_DriveSetHasSketches; - private bool m_ReadOnlyShown = false; - - public float ImageAspect { get { return m_ImageAspect; } } - - override public void SetInIntroMode(bool inIntro) - { - m_NewSketchButton.SetActive(inIntro); - m_CloseButton.SetActive(!inIntro); - - // When we switch in to intro mode, make our panel colorful, even if it doesn't have focus, - // to help attract attention. - if (inIntro) - { - for (int i = 0; i < m_IconScriptsOnFirstPage.Count; ++i) - { - m_IconScriptsOnFirstPage[i].SetButtonGrayscale(false); - } - for (int i = 0; i < m_IconScriptsOnNormalPage.Count; ++i) - { - m_IconScriptsOnNormalPage[i].SetButtonGrayscale(false); - } - } - } - - protected override List Icons - { - get - { - return (PageIndex == 0 ? m_IconScriptsOnFirstPage : m_IconScriptsOnNormalPage); - } - } - - public override bool IsInButtonMode(ModeButton button) - { - GalleryButton galleryButton = button as GalleryButton; - return galleryButton && - ((galleryButton.m_ButtonType == GalleryButton.Type.Liked && m_CurrentSketchSet == SketchSetType.Liked) || - (galleryButton.m_ButtonType == GalleryButton.Type.Local && m_CurrentSketchSet == SketchSetType.User) || - (galleryButton.m_ButtonType == GalleryButton.Type.Showcase && m_CurrentSketchSet == SketchSetType.Curated) || - (galleryButton.m_ButtonType == GalleryButton.Type.Drive && m_CurrentSketchSet == SketchSetType.Drive)); - } - - override public void InitPanel() - { - base.InitPanel(); - - m_NewSketchButtonScript = m_NewSketchButton.GetComponent(); - m_PaintButtonScript = m_CloseButton.GetComponent(); - m_IconScriptsOnFirstPage = new List(); - for (int i = 0; i < m_IconsOnFirstPage.Length; ++i) - { - m_IconScriptsOnFirstPage.Add(m_IconsOnFirstPage[i].GetComponent()); - } - m_IconScriptsOnNormalPage = new List(); - for (int i = 0; i < m_IconsOnNormalPage.Length; ++i) - { - m_IconScriptsOnNormalPage.Add(m_IconsOnNormalPage[i].GetComponent()); - } - SetInIntroMode(false); - - Debug.Assert(m_SketchIconUvScale.x >= 0.0f && m_SketchIconUvScale.x <= 1.0f && - m_SketchIconUvScale.y >= 0.0f && m_SketchIconUvScale.y <= 1.0f); - m_HalfInvUvScale.Set(1.0f - m_SketchIconUvScale.x, 1.0f - m_SketchIconUvScale.y); - m_HalfInvUvScale *= 0.5f; - } - - protected override void OnStart() - { - // Initialize icons. - LoadSketchButton[] rPanelButtons = m_Mesh.GetComponentsInChildren(); - foreach (LoadSketchButton icon in rPanelButtons) - { - GameObject go = icon.gameObject; - go.SetActive(false); - } - - // GameObject is active in prefab so the button registers. - m_NoLikesMessage.SetActive(false); - m_NotLoggedInMessage.SetActive(false); - m_NotLoggedInDriveMessage.SetActive(false); - - // Dynamically position the gallery buttons. - OnDriveSetHasSketchesChanged(); - - // Set the sketch set var to Liked, then function set to force state. - m_CurrentSketchSet = SketchSetType.Liked; - SetVisibleSketchSet(SketchSetType.User); - - Action refresh = () => - { - if (m_ContactingServerMessage.activeSelf || - m_NoShowcaseMessage.activeSelf || - m_LoadingGallery.activeSelf) - { - // Update the overlays more frequently when these overlays are shown to reflect whether - // we are actively trying to get sketches from Poly. - RefreshPage(); - } - }; - SketchCatalog.m_Instance.GetSet(SketchSetType.Liked).OnSketchRefreshingChanged += refresh; - SketchCatalog.m_Instance.GetSet(SketchSetType.Curated).OnSketchRefreshingChanged += refresh; - SketchCatalog.m_Instance.GetSet(SketchSetType.Drive).OnSketchRefreshingChanged += refresh; - App.GoogleIdentity.OnLogout += refresh; - } - - void OnDestroy() - { - if (m_SketchSet != null) - { - m_SketchSet.OnChanged -= OnSketchSetDirty; - } - } - - override protected void OnEnablePanel() - { - base.OnEnablePanel(); - if (m_SketchSet != null) - { - m_SketchSet.RequestRefresh(); - } - } - - void SetVisibleSketchSet(SketchSetType type) - { - if (m_CurrentSketchSet != type) - { - // Clean up our old sketch set. - if (m_SketchSet != null) - { - m_SketchSet.OnChanged -= OnSketchSetDirty; - } - - // Cache new set. - m_SketchSet = SketchCatalog.m_Instance.GetSet(type); - m_SketchSet.OnChanged += OnSketchSetDirty; - m_SketchSet.RequestRefresh(); - - // Tell all the icons which set to reference when loading sketches. - IEnumerable allIcons = m_IconsOnFirstPage.Concat(m_IconsOnNormalPage) - .Select(icon => icon.GetComponent()) - .Where(icon => icon != null); - foreach (LoadSketchButton icon in allIcons) - { - icon.SketchSet = m_SketchSet; - } - - ComputeNumPages(); - ResetPageIndex(); - m_CurrentSketchSet = type; - RefreshPage(); - - switch (m_CurrentSketchSet) - { - case SketchSetType.User: - m_PanelTextPro.text = PanelTextStandard; - break; - case SketchSetType.Curated: - m_PanelTextPro.text = PanelTextShowcase; - break; - case SketchSetType.Liked: - m_PanelTextPro.text = PanelTextLiked; - break; - case SketchSetType.Drive: - m_PanelTextPro.text = PanelTextDrive; - break; - } - } - } - - private void ComputeNumPages() - { - if (m_SketchSet.NumSketches <= m_IconsOnFirstPage.Length) - { - m_NumPages = 1; - return; - } - int remainingSketches = m_SketchSet.NumSketches - m_IconsOnFirstPage.Length; - int normalPages = ((remainingSketches - 1) / m_IconsOnNormalPage.Length) + 1; - m_NumPages = 1 + normalPages; - } - - List GetIconLoadIndices() - { - var ret = new List(); - for (int i = 0; i < Icons.Count; i++) - { - int sketchIndex = m_IndexOffset + i; - if (sketchIndex >= m_SketchSet.NumSketches) - { - break; - } - ret.Add(sketchIndex); - } - return ret; - } - - protected override void RefreshPage() - { - m_SketchSet.RequestOnlyLoadedMetadata(GetIconLoadIndices()); - m_AllIconTexturesAssigned = false; - m_AllSketchesAreAvailable = false; - - // Disable all. - foreach (var i in m_IconsOnFirstPage) - { - i.SetActive(false); - } - foreach (var i in m_IconsOnNormalPage) - { - i.SetActive(false); - } - - // Base Refresh updates the modal parts of the panel, and we always want those refreshed. - base.RefreshPage(); - - bool requiresPoly = m_CurrentSketchSet == SketchSetType.Liked; - - bool polyDown = VrAssetService.m_Instance.NoConnection && requiresPoly; - m_NoPolyConnectionMessage.SetActive(polyDown); - - bool outOfDate = !polyDown && !VrAssetService.m_Instance.Available && requiresPoly; - m_OutOfDateMessage.SetActive(outOfDate); - - if (outOfDate || polyDown) - { - m_NoSketchesMessage.SetActive(false); - m_NoDriveSketchesMessage.SetActive(false); - m_NotLoggedInMessage.SetActive(false); - m_NoLikesMessage.SetActive(false); - m_ContactingServerMessage.SetActive(false); - m_NoShowcaseMessage.SetActive(false); - return; - } - - bool refreshIcons = m_SketchSet.NumSketches > 0; - - // Show no sketches if we don't have sketches. - m_NoSketchesMessage.SetActive( - (m_CurrentSketchSet == SketchSetType.User) && (m_SketchSet.NumSketches <= 0)); - m_NoDriveSketchesMessage.SetActive( - (m_CurrentSketchSet == SketchSetType.Drive) && (m_SketchSet.NumSketches <= 0)); - - // Show sign in popup if signed out for liked or drive sketchsets - bool showNotLoggedIn = !App.GoogleIdentity.LoggedIn && - (m_CurrentSketchSet == SketchSetType.Liked || - m_CurrentSketchSet == SketchSetType.Drive); - refreshIcons = refreshIcons && !showNotLoggedIn; - m_NotLoggedInMessage.SetActive(showNotLoggedIn && m_CurrentSketchSet == SketchSetType.Liked); - m_NotLoggedInDriveMessage.SetActive(showNotLoggedIn && - m_CurrentSketchSet == SketchSetType.Drive); - - // Show no likes text & gallery button if we don't have liked sketches. - m_NoLikesMessage.SetActive( - (m_CurrentSketchSet == SketchSetType.Liked) && - (m_SketchSet.NumSketches <= 0) && - !m_SketchSet.IsActivelyRefreshingSketches && - App.GoogleIdentity.LoggedIn); - - // Show Contacting Server if we're talking to Poly. - m_ContactingServerMessage.SetActive( - (requiresPoly || - m_CurrentSketchSet == SketchSetType.Drive) && - (m_SketchSet.NumSketches <= 0) && - (m_SketchSet.IsActivelyRefreshingSketches && App.GoogleIdentity.LoggedIn)); - - // Show Showcase error if we're in Showcase and don't have sketches. - m_NoShowcaseMessage.SetActive( - (m_CurrentSketchSet == SketchSetType.Curated) && - (m_SketchSet.NumSketches <= 0) && - !m_SketchSet.IsActivelyRefreshingSketches); - - // Refresh all icons if necessary. - if (!refreshIcons) - { - return; - } - - for (int i = 0; i < Icons.Count; i++) - { - LoadSketchButton icon = Icons[i] as LoadSketchButton; - // Default to loading image - icon.SetButtonTexture(m_LoadingImageTexture); - icon.ThumbnailLoaded = false; - - // Set sketch index relative to page based index - int iSketchIndex = m_IndexOffset + i; - if (iSketchIndex >= m_SketchSet.NumSketches) - { - iSketchIndex = -1; - } - icon.SketchIndex = iSketchIndex; - icon.ResetScale(); - - // Init icon according to availability of sketch - GameObject go = icon.gameObject; - if (m_SketchSet.IsSketchIndexValid(iSketchIndex)) - { - string sSketchName = m_SketchSet.GetSketchName(iSketchIndex); - icon.SetDescriptionText(App.ShortenForDescriptionText(sSketchName)); - SceneFileInfo info = m_SketchSet.GetSketchSceneFileInfo(iSketchIndex); - if (info.Available) - { - m_SketchSet.PrecacheSketchModels(iSketchIndex); - } - - if (info.TriangleCount is int triCount) - { - icon.WarningVisible = triCount > - QualityControls.m_Instance.AppQualityLevels.WarningPolySketchTriangles; - } - else - { - icon.WarningVisible = false; - } - go.SetActive(true); - } - else - { - go.SetActive(false); - } - } - } - - void Update() - { - BaseUpdate(); - PageFlipUpdate(); - - // Refresh icons while they are in flux - if (m_SketchSet.IsReadyForAccess && - (!m_SketchSet.RequestedIconsAreLoaded || - !m_AllIconTexturesAssigned || !m_AllSketchesAreAvailable)) - { - UpdateIcons(); - } - - // Set icon uv offsets relative to head position. - Vector3 head_LS = m_Mesh.transform.InverseTransformPoint(ViewpointScript.Head.position); - float angleX = Vector3.Angle(Vector3.back, new Vector3(head_LS.x, 0.0f, head_LS.z)); - angleX *= (head_LS.x > 0.0f) ? -1.0f : 1.0f; - - float angleY = Vector3.Angle(Vector3.back, new Vector3(0.0f, head_LS.y, head_LS.z)); - angleY *= (head_LS.y > 0.0f) ? -1.0f : 1.0f; - - float maxAngleXRatio = angleX / 90.0f; - float maxAngleYRatio = angleY / 90.0f; - Vector2 offset = new Vector2( - m_HalfInvUvScale.x + (m_HalfInvUvScale.x * maxAngleXRatio), - m_HalfInvUvScale.y + (m_HalfInvUvScale.y * maxAngleYRatio)); - for (int i = 0; i < Icons.Count; i++) - { - LoadSketchButton icon = Icons[i] as LoadSketchButton; - icon.UpdateUvOffsetAndScale(offset, m_SketchIconUvScale); - } - - switch (m_CurrentSketchSet) - { - case SketchSetType.Curated: - m_LoadingGallery.SetActive(m_SketchSet.IsActivelyRefreshingSketches); - m_DriveSyncProgress.SetActive(false); - m_SyncingDriveIcon.SetActive(false); - m_DriveEnabledIcon.SetActive(false); - m_DriveDisabledIcon.SetActive(false); - m_DriveFullIcon.SetActive(false); - break; - case SketchSetType.Liked: - m_LoadingGallery.SetActive(false); - m_DriveSyncProgress.SetActive(false); - m_SyncingDriveIcon.SetActive(false); - m_DriveEnabledIcon.SetActive(false); - m_DriveDisabledIcon.SetActive(false); - m_DriveFullIcon.SetActive(false); - break; - case SketchSetType.User: - case SketchSetType.Drive: - bool sketchSetRefreshing = m_CurrentSketchSet == SketchSetType.Drive && - m_SketchSet.IsActivelyRefreshingSketches; - bool driveSyncing = App.DriveSync.Syncing; - bool syncEnabled = App.DriveSync.SyncEnabled; - bool googleLoggedIn = App.GoogleIdentity.LoggedIn; - bool driveFull = App.DriveSync.DriveIsLowOnSpace; - m_LoadingGallery.SetActive(sketchSetRefreshing && !driveSyncing); - m_DriveSyncProgress.SetActive(driveSyncing && !driveFull); - m_SyncingDriveIcon.SetActive(driveSyncing && !driveFull); - m_DriveEnabledIcon.SetActive(!driveFull && !driveSyncing && syncEnabled && googleLoggedIn); - m_DriveDisabledIcon.SetActive(!syncEnabled && googleLoggedIn); - m_DriveFullIcon.SetActive(driveFull && syncEnabled && googleLoggedIn); - break; - } - - // Check to see if whether "drive set has sketches" has changed. - bool driveSetHasSketches = - SketchCatalog.m_Instance.GetSet(SketchSetType.Drive).NumSketches != 0; - if (m_DriveSetHasSketches != driveSetHasSketches) - { - m_DriveSetHasSketches = driveSetHasSketches; - OnDriveSetHasSketchesChanged(); - } - } - - // Whether or not the Google Drive set has any sketches impacts how the gallery buttons are - // laid out. - private void OnDriveSetHasSketchesChanged() - { - // Only show the Google Drive gallery tab if there are sketches in there. - int galleryButtonAvailable = m_GalleryButtons.Length; - int galleryButtonN; - if (m_DriveSetHasSketches) - { - m_GalleryButtons[m_ElementNumberGalleryButtonDrive].gameObject.SetActive(true); - galleryButtonN = galleryButtonAvailable; - } - else - { - m_GalleryButtons[m_ElementNumberGalleryButtonDrive].gameObject.SetActive(false); - galleryButtonN = galleryButtonAvailable - 1; - - if (m_CurrentSketchSet == SketchSetType.Drive) - { - // We were on the Drive tab but it's gone away so switch to the local tab by simulating - // the user pressing the local tab button. - ButtonPressed(GalleryButton.Type.Local); - } - } - - // Position the gallery buttons so that they're centered. - float buttonPosY = (0.5f * (galleryButtonN - 1) * m_GalleryButtonHeight - + kGalleryButtonLocalPadding); - for (int i = 0; i < galleryButtonAvailable; i++) - { - if (i == m_ElementNumberGalleryButtonDrive && !m_DriveSetHasSketches) - { - continue; - } - Vector3 buttonPos = m_GalleryButtons[i].transform.localPosition; - buttonPos.y = buttonPosY; - m_GalleryButtons[i].transform.localPosition = buttonPos; - buttonPosY -= m_GalleryButtonHeight; - if (i == kElementNumberGalleryButtonLocal) - { - buttonPosY -= kGalleryButtonLocalPadding; - } - } - } - - // UpdateIcons() is called repeatedly by Update() until these three conditions are met: - // 1: The SketchSet has loaded all the requested icons - // 2: The textures for all the buttons have been set - // 3: (Cloud only) The SketchSet has downloaded the corresponding .tilt files. - // Until the .tilt file is downloaded we set a fade on the button, and need to keep updating - // until the file is downloaded. - private void UpdateIcons() - { - m_AllIconTexturesAssigned = true; - m_AllSketchesAreAvailable = true; - - // Poll sketch catalog until icons have loaded - foreach (BaseButton baseButton in Icons) - { - LoadSketchButton icon = baseButton as LoadSketchButton; - if (icon == null) { continue; } - int iSketchIndex = icon.SketchIndex; - if (m_SketchSet.IsSketchIndexValid(iSketchIndex)) - { - icon.FadeIn = m_SketchSet.GetSketchSceneFileInfo(iSketchIndex).Available ? 1f : 0.5f; - - if (!icon.ThumbnailLoaded) - { - Texture2D rTexture = null; - string[] authors; - string description; - if (m_SketchSet.GetSketchIcon(iSketchIndex, out rTexture, out authors, out description)) - { - if (rTexture != null) - { - // Pass through aspect ratio of image so we don't get squished - // thumbnails from Poly - m_ImageAspect = (float)rTexture.width / rTexture.height; - float aspect = m_ImageAspect; - icon.SetButtonTexture(rTexture, aspect); - } - else - { - icon.SetButtonTexture(m_UnknownImageTexture); - } - - // Mark the texture as assigned regardless of actual bits being valid - icon.ThumbnailLoaded = true; - ; - List lines = new List(); - lines.Add(icon.Description); - - SceneFileInfo info = m_SketchSet.GetSketchSceneFileInfo(iSketchIndex); - if (info is PolySceneFileInfo polyInfo && - polyInfo.License != VrAssetService.kCreativeCommonsLicense) - { - lines.Add(String.Format("© {0}", authors[0])); - lines.Add("All Rights Reserved"); - } - else - { - // Include primary author in description if available - if (authors != null && authors.Length > 0) - { - lines.Add(authors[0]); - } - // Include an actual description - if (description != null) - { - lines.Add(App.ShortenForDescriptionText(description)); - } - } - icon.SetDescriptionText(lines.ToArray()); - } - else - { - // While metadata has not finished loading, check if this file is valid - bool bFileValid = false; - SceneFileInfo rInfo = m_SketchSet.GetSketchSceneFileInfo(iSketchIndex); - if (rInfo != null) - { - bFileValid = rInfo.Exists; - } - - // If this file isn't valid, just keep the defaults and move on - if (!bFileValid) - { - icon.SetButtonTexture(m_UnknownImageTexture); - icon.ThumbnailLoaded = true; - } - else - { - m_AllIconTexturesAssigned = false; - } - if (!rInfo.Available) - { - m_AllSketchesAreAvailable = false; - } - } - } - } - } - } - - override public void OnUpdatePanel(Vector3 vToPanel, Vector3 vHitPoint) - { - base.OnUpdatePanel(vToPanel, vHitPoint); - - // Icons are active when animations aren't. - bool bButtonsAvailable = - (m_CurrentPageFlipState == PageFlipState.Standard) && (m_ActivePopUp == null); - - if (!PanelManager.m_Instance.IntroSketchbookMode) - { - if (bButtonsAvailable && - DoesRayHitCollider(m_ReticleSelectionRay, m_PaintButtonScript.GetCollider())) - { - m_PaintButtonScript.UpdateButtonState(m_InputValid); - } - else - { - m_PaintButtonScript.ResetState(); - } - } - else - { - if (bButtonsAvailable && - DoesRayHitCollider(m_ReticleSelectionRay, m_NewSketchButtonScript.GetCollider())) - { - m_NewSketchButtonScript.UpdateButtonState(m_InputValid); - } - else - { - m_NewSketchButtonScript.ResetState(); - } - } - } - - override protected void OnUpdateActive() - { - // If we're not active, hide all our preview panels - if (!m_GazeActive) - { - m_OnlineGalleryButtonRenderer.material.SetFloat("_Grayscale", 1); - m_ProfileButtonRenderer.material.SetFloat("_Grayscale", 1); - - for (int i = 0; i < m_IconScriptsOnFirstPage.Count; ++i) - { - m_IconScriptsOnFirstPage[i].ResetState(); - } - for (int i = 0; i < m_IconScriptsOnNormalPage.Count; ++i) - { - m_IconScriptsOnNormalPage[i].ResetState(); - } - if (m_NewSketchButtonScript) - { - m_NewSketchButtonScript.ResetState(); - } - if (m_PaintButtonScript) - { - m_PaintButtonScript.ResetState(); - } - } - else if (m_CurrentState == PanelState.Available) - { - m_OnlineGalleryButtonRenderer.material.SetFloat("_Grayscale", 0); - m_ProfileButtonRenderer.material.SetFloat("_Grayscale", 0); - m_SketchSet.RequestRefresh(); - } - } - - override protected void OnUpdateGazeBehavior(Color rPanelColor) - { - // Set the appropriate dim value for all our buttons and sliders - if (Icons != null) - { - foreach (BaseButton icon in Icons) - { - icon.SetColor(rPanelColor); - } - } - - if (m_NewSketchButtonScript != null) - { - m_NewSketchButtonScript.SetColor(rPanelColor); - } - - if (m_NavigationButtons != null) - { - for (int i = 0; i < m_NavigationButtons.Length; ++i) - { - m_NavigationButtons[i].SetColor(rPanelColor); - } - } - } - - override public bool RaycastAgainstMeshCollider(Ray rRay, out RaycastHit rHitInfo, float fDist) - { - if (m_NewSketchButton.GetComponent().Raycast(rRay, out rHitInfo, fDist)) - { - return true; - } - return base.RaycastAgainstMeshCollider(rRay, out rHitInfo, fDist); - } - - // Works specifically with GalleryButtons. - public void ButtonPressed(GalleryButton.Type rType, BaseButton button = null) - { - switch (rType) - { - case GalleryButton.Type.Exit: - SketchSurfacePanel.m_Instance.EnableDefaultTool(); - PointerManager.m_Instance.EatLineEnabledInput(); - break; - case GalleryButton.Type.Showcase: - SetVisibleSketchSet(SketchSetType.Curated); - break; - case GalleryButton.Type.Local: - SetVisibleSketchSet(SketchSetType.User); - break; - case GalleryButton.Type.Liked: - SetVisibleSketchSet(SketchSetType.Liked); - break; - case GalleryButton.Type.Drive: - SetVisibleSketchSet(SketchSetType.Drive); - if (!m_ReadOnlyShown) - { - CreatePopUp(SketchControlsScript.GlobalCommands.ReadOnlyNotice, - -1, -1, m_ReadOnlyPopupOffset); - if (button != null) - { - button.ResetState(); - } - m_ReadOnlyShown = true; - } - break; - default: - break; - } - } - - private void OnSketchSetDirty() - { - ComputeNumPages(); - - SceneFileInfo first = (m_SketchSet.NumSketches > 0) ? - m_SketchSet.GetSketchSceneFileInfo(0) : null; - // If first sketch changed, return to first page. - if (m_FirstSketch != null && !m_FirstSketch.Equals(first)) - { - PageIndex = 0; - } - else - { - PageIndex = Mathf.Min(PageIndex, m_NumPages - 1); - } - m_FirstSketch = first; - GotoPage(PageIndex); - UpdateIndexOffset(); - RefreshPage(); - } - - override protected void UpdateIndexOffset() - { - m_IndexOffset = PageIndex == 0 ? 0 : m_IconsOnFirstPage.Length + (PageIndex - 1) * Icons.Count; - } - } -} // namespace TiltBrush +// Copyright 2020 The Tilt Brush Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// 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 UnityEngine.Localization; +using System; +using System.Collections.Generic; +using System.Linq; +using TMPro; +using UnityEngine.Serialization; + +namespace TiltBrush +{ + + public class SketchbookPanel : ModalPanel + { + // Index of the "local sketches" button in m_GalleryButtons + const int kElementNumberGalleryButtonLocal = 0; + // Amount of extra space to put below the "local sketches" gallery button + const float kGalleryButtonLocalPadding = .15f; + + [SerializeField] private Texture2D m_LoadingImageTexture; + [SerializeField] private Texture2D m_UnknownImageTexture; + [SerializeField] private TextMeshPro m_PanelTextPro; + [SerializeField] private LocalizedString m_PanelTextStandard; + public string PanelTextStandard { get { return m_PanelTextStandard.GetLocalizedStringAsync().Result; } } + [SerializeField] private LocalizedString m_PanelTextShowcase; + public string PanelTextShowcase { get { return m_PanelTextShowcase.GetLocalizedStringAsync().Result; } } + + [SerializeField] private LocalizedString m_PanelTextLiked; + public string PanelTextLiked { get { return m_PanelTextLiked.GetLocalizedStringAsync().Result; } } + [SerializeField] private LocalizedString m_PanelTextDrive; + public string PanelTextDrive { get { return m_PanelTextDrive.GetLocalizedStringAsync().Result; } } + [SerializeField] private GameObject m_NoSketchesMessage; + [SerializeField] private GameObject m_NoDriveSketchesMessage; + [SerializeField] private GameObject m_NoLikesMessage; + [SerializeField] private GameObject m_NotLoggedInMessage; + [SerializeField] private GameObject m_NotLoggedInDriveMessage; + [SerializeField] private GameObject m_NoShowcaseMessage; + [SerializeField] private GameObject m_ContactingServerMessage; + [SerializeField] private GameObject m_OutOfDateMessage; + [FormerlySerializedAs("m_NoPolyConnectionMessage")][SerializeField] private GameObject m_NoIcosaConnectionMessage; + [SerializeField] private Renderer m_OnlineGalleryButtonRenderer; + [SerializeField] private GameObject[] m_IconsOnFirstPage; + [SerializeField] private GameObject[] m_IconsOnNormalPage; + [SerializeField] private GameObject m_CloseButton; + [SerializeField] private GameObject m_NewSketchButton; + // Gallery buttons will automatically reposition based on how many are visible so they must be + // added to this array in order from top to bottom. + [SerializeField] private GalleryButton[] m_GalleryButtons; + [SerializeField] private int m_ElementNumberGalleryButtonDrive = 3; + [SerializeField] private float m_GalleryButtonHeight = 0.3186f; + [SerializeField] private Renderer m_ProfileButtonRenderer; + [SerializeField] private GameObject m_LoadingGallery; + [SerializeField] private GameObject m_DriveSyncProgress; + [SerializeField] private GameObject m_SyncingDriveIcon; + [SerializeField] private GameObject m_DriveEnabledIcon; + [SerializeField] private GameObject m_DriveDisabledIcon; + [SerializeField] private GameObject m_DriveFullIcon; + [SerializeField] private Vector2 m_SketchIconUvScale = new Vector2(0.7f, 0.7f); + [SerializeField] private Vector3 m_ReadOnlyPopupOffset; + + private float m_ImageAspect; + private Vector2 m_HalfInvUvScale; + + private SceneFileInfo m_FirstSketch; + + private bool m_AllIconTexturesAssigned; + private bool m_AllSketchesAreAvailable; + private SketchSetType m_CurrentSketchSet; + private SketchSet m_SketchSet; + private OptionButton m_NewSketchButtonScript; + private OptionButton m_PaintButtonScript; + private List m_IconScriptsOnFirstPage; + private List m_IconScriptsOnNormalPage; + private bool m_DriveSetHasSketches; + private bool m_ReadOnlyShown = false; + + public float ImageAspect { get { return m_ImageAspect; } } + + override public void SetInIntroMode(bool inIntro) + { + m_NewSketchButton.SetActive(inIntro); + m_CloseButton.SetActive(!inIntro); + + // When we switch in to intro mode, make our panel colorful, even if it doesn't have focus, + // to help attract attention. + if (inIntro) + { + for (int i = 0; i < m_IconScriptsOnFirstPage.Count; ++i) + { + m_IconScriptsOnFirstPage[i].SetButtonGrayscale(false); + } + for (int i = 0; i < m_IconScriptsOnNormalPage.Count; ++i) + { + m_IconScriptsOnNormalPage[i].SetButtonGrayscale(false); + } + } + } + + protected override List Icons + { + get + { + return (PageIndex == 0 ? m_IconScriptsOnFirstPage : m_IconScriptsOnNormalPage); + } + } + + public override bool IsInButtonMode(ModeButton button) + { + GalleryButton galleryButton = button as GalleryButton; + return galleryButton && + ((galleryButton.m_ButtonType == GalleryButton.Type.Liked && m_CurrentSketchSet == SketchSetType.Liked) || + (galleryButton.m_ButtonType == GalleryButton.Type.Local && m_CurrentSketchSet == SketchSetType.User) || + (galleryButton.m_ButtonType == GalleryButton.Type.Showcase && m_CurrentSketchSet == SketchSetType.Curated) || + (galleryButton.m_ButtonType == GalleryButton.Type.Drive && m_CurrentSketchSet == SketchSetType.Drive)); + } + + override public void InitPanel() + { + base.InitPanel(); + + m_NewSketchButtonScript = m_NewSketchButton.GetComponent(); + m_PaintButtonScript = m_CloseButton.GetComponent(); + m_IconScriptsOnFirstPage = new List(); + for (int i = 0; i < m_IconsOnFirstPage.Length; ++i) + { + m_IconScriptsOnFirstPage.Add(m_IconsOnFirstPage[i].GetComponent()); + } + m_IconScriptsOnNormalPage = new List(); + for (int i = 0; i < m_IconsOnNormalPage.Length; ++i) + { + m_IconScriptsOnNormalPage.Add(m_IconsOnNormalPage[i].GetComponent()); + } + SetInIntroMode(false); + + Debug.Assert(m_SketchIconUvScale.x >= 0.0f && m_SketchIconUvScale.x <= 1.0f && + m_SketchIconUvScale.y >= 0.0f && m_SketchIconUvScale.y <= 1.0f); + m_HalfInvUvScale.Set(1.0f - m_SketchIconUvScale.x, 1.0f - m_SketchIconUvScale.y); + m_HalfInvUvScale *= 0.5f; + } + + protected override void OnStart() + { + // Initialize icons. + LoadSketchButton[] rPanelButtons = m_Mesh.GetComponentsInChildren(); + foreach (LoadSketchButton icon in rPanelButtons) + { + GameObject go = icon.gameObject; + go.SetActive(false); + } + + // GameObject is active in prefab so the button registers. + m_NoLikesMessage.SetActive(false); + m_NotLoggedInMessage.SetActive(false); + m_NotLoggedInDriveMessage.SetActive(false); + + // Dynamically position the gallery buttons. + OnDriveSetHasSketchesChanged(); + + // Set the sketch set var to Liked, then function set to force state. + m_CurrentSketchSet = SketchSetType.Liked; + SetVisibleSketchSet(SketchSetType.User); + + Action refresh = () => + { + if (m_ContactingServerMessage.activeSelf || + m_NoShowcaseMessage.activeSelf || + m_LoadingGallery.activeSelf) + { + // Update the overlays more frequently when these overlays are shown to reflect whether + // we are actively trying to get sketches from Poly. + RefreshPage(); + } + }; + SketchCatalog.m_Instance.GetSet(SketchSetType.Liked).OnSketchRefreshingChanged += refresh; + SketchCatalog.m_Instance.GetSet(SketchSetType.Curated).OnSketchRefreshingChanged += refresh; + SketchCatalog.m_Instance.GetSet(SketchSetType.Drive).OnSketchRefreshingChanged += refresh; + App.GoogleIdentity.OnLogout += refresh; + } + + void OnDestroy() + { + if (m_SketchSet != null) + { + m_SketchSet.OnChanged -= OnSketchSetDirty; + } + } + + override protected void OnEnablePanel() + { + base.OnEnablePanel(); + if (m_SketchSet != null) + { + m_SketchSet.RequestRefresh(); + } + } + + void SetVisibleSketchSet(SketchSetType type) + { + if (m_CurrentSketchSet != type) + { + // Clean up our old sketch set. + if (m_SketchSet != null) + { + m_SketchSet.OnChanged -= OnSketchSetDirty; + } + + // Cache new set. + m_SketchSet = SketchCatalog.m_Instance.GetSet(type); + m_SketchSet.OnChanged += OnSketchSetDirty; + m_SketchSet.RequestRefresh(); + + // Tell all the icons which set to reference when loading sketches. + IEnumerable allIcons = m_IconsOnFirstPage.Concat(m_IconsOnNormalPage) + .Select(icon => icon.GetComponent()) + .Where(icon => icon != null); + foreach (LoadSketchButton icon in allIcons) + { + icon.SketchSet = m_SketchSet; + } + + ComputeNumPages(); + ResetPageIndex(); + m_CurrentSketchSet = type; + RefreshPage(); + + switch (m_CurrentSketchSet) + { + case SketchSetType.User: + m_PanelTextPro.text = PanelTextStandard; + break; + case SketchSetType.Curated: + m_PanelTextPro.text = PanelTextShowcase; + break; + case SketchSetType.Liked: + m_PanelTextPro.text = PanelTextLiked; + break; + case SketchSetType.Drive: + m_PanelTextPro.text = PanelTextDrive; + break; + } + } + } + + private void ComputeNumPages() + { + if (m_SketchSet.NumSketches <= m_IconsOnFirstPage.Length) + { + m_NumPages = 1; + return; + } + int remainingSketches = m_SketchSet.NumSketches - m_IconsOnFirstPage.Length; + int normalPages = ((remainingSketches - 1) / m_IconsOnNormalPage.Length) + 1; + m_NumPages = 1 + normalPages; + } + + List GetIconLoadIndices() + { + var ret = new List(); + for (int i = 0; i < Icons.Count; i++) + { + int sketchIndex = m_IndexOffset + i; + if (sketchIndex >= m_SketchSet.NumSketches) + { + break; + } + ret.Add(sketchIndex); + } + return ret; + } + + protected override void RefreshPage() + { + m_SketchSet.RequestOnlyLoadedMetadata(GetIconLoadIndices()); + m_AllIconTexturesAssigned = false; + m_AllSketchesAreAvailable = false; + + // Disable all. + foreach (var i in m_IconsOnFirstPage) + { + i.SetActive(false); + } + foreach (var i in m_IconsOnNormalPage) + { + i.SetActive(false); + } + + // Base Refresh updates the modal parts of the panel, and we always want those refreshed. + base.RefreshPage(); + + bool requiresIcosa = m_CurrentSketchSet == SketchSetType.Liked || m_CurrentSketchSet == SketchSetType.Curated; + bool requiresGoogle = m_CurrentSketchSet == SketchSetType.Drive; + + bool icosaDown = VrAssetService.m_Instance.NoConnection && requiresIcosa; + m_NoIcosaConnectionMessage.SetActive(icosaDown); + + bool outOfDate = !icosaDown && !VrAssetService.m_Instance.Available && requiresIcosa; + m_OutOfDateMessage.SetActive(outOfDate); + + if (outOfDate || icosaDown) + { + m_NoSketchesMessage.SetActive(false); + m_NoDriveSketchesMessage.SetActive(false); + m_NotLoggedInMessage.SetActive(false); + m_NoLikesMessage.SetActive(false); + m_ContactingServerMessage.SetActive(false); + m_NoShowcaseMessage.SetActive(false); + return; + } + + bool refreshIcons = m_SketchSet.NumSketches > 0; + + // Show no sketches if we don't have sketches. + m_NoSketchesMessage.SetActive( + (m_CurrentSketchSet == SketchSetType.User) && (m_SketchSet.NumSketches <= 0)); + m_NoDriveSketchesMessage.SetActive( + (m_CurrentSketchSet == SketchSetType.Drive) && (m_SketchSet.NumSketches <= 0)); + + // Show sign in popup if signed out for liked or drive sketchsets + bool showIcosaNotLoggedIn = !App.IcosaIsLoggedIn && m_CurrentSketchSet == SketchSetType.Liked; + bool showGoogleNotLoggedIn = !App.GoogleIdentity.LoggedIn && m_CurrentSketchSet == SketchSetType.Drive; + refreshIcons = refreshIcons && !showIcosaNotLoggedIn; + m_NotLoggedInMessage.SetActive(showIcosaNotLoggedIn && m_CurrentSketchSet == SketchSetType.Liked); + m_NotLoggedInDriveMessage.SetActive(showGoogleNotLoggedIn); + + // Show no likes text & gallery button if we don't have liked sketches. + m_NoLikesMessage.SetActive( + (m_CurrentSketchSet == SketchSetType.Liked) && + (m_SketchSet.NumSketches <= 0) && + !m_SketchSet.IsActivelyRefreshingSketches && + App.IcosaIsLoggedIn); + + // Show Contacting Server if we're talking to Drive or Icosa + m_ContactingServerMessage.SetActive( + m_SketchSet.NumSketches <= 0 + && m_SketchSet.IsActivelyRefreshingSketches + && ( + (requiresIcosa && App.IcosaIsLoggedIn) || + (requiresGoogle && App.GoogleIdentity.LoggedIn) + )); + + // Show Showcase error if we're in Showcase and don't have sketches. + m_NoShowcaseMessage.SetActive( + (m_CurrentSketchSet == SketchSetType.Curated) && + (m_SketchSet.NumSketches <= 0) && + !m_SketchSet.IsActivelyRefreshingSketches); + + // Refresh all icons if necessary. + if (!refreshIcons) + { + return; + } + + for (int i = 0; i < Icons.Count; i++) + { + LoadSketchButton icon = Icons[i] as LoadSketchButton; + // Default to loading image + icon.SetButtonTexture(m_LoadingImageTexture); + icon.ThumbnailLoaded = false; + + // Set sketch index relative to page based index + int iSketchIndex = m_IndexOffset + i; + if (iSketchIndex >= m_SketchSet.NumSketches) + { + iSketchIndex = -1; + } + icon.SketchIndex = iSketchIndex; + icon.ResetScale(); + + // Init icon according to availability of sketch + GameObject go = icon.gameObject; + if (m_SketchSet.IsSketchIndexValid(iSketchIndex)) + { + string sSketchName = m_SketchSet.GetSketchName(iSketchIndex); + icon.SetDescriptionText(App.ShortenForDescriptionText(sSketchName)); + SceneFileInfo info = m_SketchSet.GetSketchSceneFileInfo(iSketchIndex); + if (info.Available) + { + m_SketchSet.PrecacheSketchModels(iSketchIndex); + } + + if (info.TriangleCount is int triCount) + { + icon.WarningVisible = triCount > + QualityControls.m_Instance.AppQualityLevels.WarningPolySketchTriangles; + } + else + { + icon.WarningVisible = false; + } + go.SetActive(true); + } + else + { + go.SetActive(false); + } + } + } + + void Update() + { + BaseUpdate(); + PageFlipUpdate(); + + // Refresh icons while they are in flux + if (m_SketchSet.IsReadyForAccess && + (!m_SketchSet.RequestedIconsAreLoaded || + !m_AllIconTexturesAssigned || !m_AllSketchesAreAvailable)) + { + UpdateIcons(); + } + + // Set icon uv offsets relative to head position. + Vector3 head_LS = m_Mesh.transform.InverseTransformPoint(ViewpointScript.Head.position); + float angleX = Vector3.Angle(Vector3.back, new Vector3(head_LS.x, 0.0f, head_LS.z)); + angleX *= (head_LS.x > 0.0f) ? -1.0f : 1.0f; + + float angleY = Vector3.Angle(Vector3.back, new Vector3(0.0f, head_LS.y, head_LS.z)); + angleY *= (head_LS.y > 0.0f) ? -1.0f : 1.0f; + + float maxAngleXRatio = angleX / 90.0f; + float maxAngleYRatio = angleY / 90.0f; + Vector2 offset = new Vector2( + m_HalfInvUvScale.x + (m_HalfInvUvScale.x * maxAngleXRatio), + m_HalfInvUvScale.y + (m_HalfInvUvScale.y * maxAngleYRatio)); + for (int i = 0; i < Icons.Count; i++) + { + LoadSketchButton icon = Icons[i] as LoadSketchButton; + icon.UpdateUvOffsetAndScale(offset, m_SketchIconUvScale); + } + + switch (m_CurrentSketchSet) + { + case SketchSetType.Curated: + m_LoadingGallery.SetActive(m_SketchSet.IsActivelyRefreshingSketches); + m_DriveSyncProgress.SetActive(false); + m_SyncingDriveIcon.SetActive(false); + m_DriveEnabledIcon.SetActive(false); + m_DriveDisabledIcon.SetActive(false); + m_DriveFullIcon.SetActive(false); + break; + case SketchSetType.Liked: + m_LoadingGallery.SetActive(false); + m_DriveSyncProgress.SetActive(false); + m_SyncingDriveIcon.SetActive(false); + m_DriveEnabledIcon.SetActive(false); + m_DriveDisabledIcon.SetActive(false); + m_DriveFullIcon.SetActive(false); + break; + case SketchSetType.User: + case SketchSetType.Drive: + bool sketchSetRefreshing = m_CurrentSketchSet == SketchSetType.Drive && + m_SketchSet.IsActivelyRefreshingSketches; + bool driveSyncing = App.DriveSync.Syncing; + bool syncEnabled = App.DriveSync.SyncEnabled; + bool googleLoggedIn = App.GoogleIdentity.LoggedIn; + bool driveFull = App.DriveSync.DriveIsLowOnSpace; + m_LoadingGallery.SetActive(sketchSetRefreshing && !driveSyncing); + m_DriveSyncProgress.SetActive(driveSyncing && !driveFull); + m_SyncingDriveIcon.SetActive(driveSyncing && !driveFull); + m_DriveEnabledIcon.SetActive(!driveFull && !driveSyncing && syncEnabled && googleLoggedIn); + m_DriveDisabledIcon.SetActive(!syncEnabled && googleLoggedIn); + m_DriveFullIcon.SetActive(driveFull && syncEnabled && googleLoggedIn); + break; + } + + // Check to see if whether "drive set has sketches" has changed. + bool driveSetHasSketches = + SketchCatalog.m_Instance.GetSet(SketchSetType.Drive).NumSketches != 0; + if (m_DriveSetHasSketches != driveSetHasSketches) + { + m_DriveSetHasSketches = driveSetHasSketches; + OnDriveSetHasSketchesChanged(); + } + } + + // Whether or not the Google Drive set has any sketches impacts how the gallery buttons are + // laid out. + private void OnDriveSetHasSketchesChanged() + { + // Only show the Google Drive gallery tab if there are sketches in there. + int galleryButtonAvailable = m_GalleryButtons.Length; + int galleryButtonN; + if (m_DriveSetHasSketches) + { + m_GalleryButtons[m_ElementNumberGalleryButtonDrive].gameObject.SetActive(true); + galleryButtonN = galleryButtonAvailable; + } + else + { + m_GalleryButtons[m_ElementNumberGalleryButtonDrive].gameObject.SetActive(false); + galleryButtonN = galleryButtonAvailable - 1; + + if (m_CurrentSketchSet == SketchSetType.Drive) + { + // We were on the Drive tab but it's gone away so switch to the local tab by simulating + // the user pressing the local tab button. + ButtonPressed(GalleryButton.Type.Local); + } + } + + // Position the gallery buttons so that they're centered. + float buttonPosY = (0.5f * (galleryButtonN - 1) * m_GalleryButtonHeight + + kGalleryButtonLocalPadding); + for (int i = 0; i < galleryButtonAvailable; i++) + { + if (i == m_ElementNumberGalleryButtonDrive && !m_DriveSetHasSketches) + { + continue; + } + Vector3 buttonPos = m_GalleryButtons[i].transform.localPosition; + buttonPos.y = buttonPosY; + m_GalleryButtons[i].transform.localPosition = buttonPos; + buttonPosY -= m_GalleryButtonHeight; + if (i == kElementNumberGalleryButtonLocal) + { + buttonPosY -= kGalleryButtonLocalPadding; + } + } + } + + // UpdateIcons() is called repeatedly by Update() until these three conditions are met: + // 1: The SketchSet has loaded all the requested icons + // 2: The textures for all the buttons have been set + // 3: (Cloud only) The SketchSet has downloaded the corresponding .tilt files. + // Until the .tilt file is downloaded we set a fade on the button, and need to keep updating + // until the file is downloaded. + private void UpdateIcons() + { + m_AllIconTexturesAssigned = true; + m_AllSketchesAreAvailable = true; + + // Poll sketch catalog until icons have loaded + foreach (BaseButton baseButton in Icons) + { + LoadSketchButton icon = baseButton as LoadSketchButton; + if (icon == null) { continue; } + int iSketchIndex = icon.SketchIndex; + if (m_SketchSet.IsSketchIndexValid(iSketchIndex)) + { + icon.FadeIn = m_SketchSet.GetSketchSceneFileInfo(iSketchIndex).Available ? 1f : 0.5f; + + if (!icon.ThumbnailLoaded) + { + Texture2D rTexture = null; + string[] authors; + string description; + if (m_SketchSet.GetSketchIcon(iSketchIndex, out rTexture, out authors, out description)) + { + if (rTexture != null) + { + // Pass through aspect ratio of image so we don't get squished + // thumbnails from Poly + m_ImageAspect = (float)rTexture.width / rTexture.height; + float aspect = m_ImageAspect; + icon.SetButtonTexture(rTexture, aspect); + } + else + { + icon.SetButtonTexture(m_UnknownImageTexture); + } + + // Mark the texture as assigned regardless of actual bits being valid + icon.ThumbnailLoaded = true; + ; + List lines = new List(); + lines.Add(icon.Description); + + SceneFileInfo info = m_SketchSet.GetSketchSceneFileInfo(iSketchIndex); + if (info is IcosaSceneFileInfo polyInfo && polyInfo.License != VrAssetService.kCreativeCommonsLicense) + { + if (authors != null && authors.Length > 0) + { + lines.Add($"© {authors[0]}"); + } + lines.Add("All Rights Reserved"); + } + else + { + // Include primary author in description if available + if (authors != null && authors.Length > 0) + { + lines.Add(authors[0]); + } + // Include an actual description + if (description != null) + { + lines.Add(App.ShortenForDescriptionText(description)); + } + } + icon.SetDescriptionText(lines.ToArray()); + } + else + { + // While metadata has not finished loading, check if this file is valid + bool bFileValid = false; + SceneFileInfo rInfo = m_SketchSet.GetSketchSceneFileInfo(iSketchIndex); + if (rInfo != null) + { + bFileValid = rInfo.Exists; + } + + // If this file isn't valid, just keep the defaults and move on + if (!bFileValid) + { + icon.SetButtonTexture(m_UnknownImageTexture); + icon.ThumbnailLoaded = true; + } + else + { + m_AllIconTexturesAssigned = false; + } + if (!rInfo.Available) + { + m_AllSketchesAreAvailable = false; + } + } + } + } + } + } + + override public void OnUpdatePanel(Vector3 vToPanel, Vector3 vHitPoint) + { + base.OnUpdatePanel(vToPanel, vHitPoint); + + // Icons are active when animations aren't. + bool bButtonsAvailable = + (m_CurrentPageFlipState == PageFlipState.Standard) && (m_ActivePopUp == null); + + if (!PanelManager.m_Instance.IntroSketchbookMode) + { + if (bButtonsAvailable && + DoesRayHitCollider(m_ReticleSelectionRay, m_PaintButtonScript.GetCollider())) + { + m_PaintButtonScript.UpdateButtonState(m_InputValid); + } + else + { + m_PaintButtonScript.ResetState(); + } + } + else + { + if (bButtonsAvailable && + DoesRayHitCollider(m_ReticleSelectionRay, m_NewSketchButtonScript.GetCollider())) + { + m_NewSketchButtonScript.UpdateButtonState(m_InputValid); + } + else + { + m_NewSketchButtonScript.ResetState(); + } + } + } + + override protected void OnUpdateActive() + { + // If we're not active, hide all our preview panels + if (!m_GazeActive) + { + m_OnlineGalleryButtonRenderer.material.SetFloat("_Grayscale", 1); + m_ProfileButtonRenderer.material.SetFloat("_Grayscale", 1); + + for (int i = 0; i < m_IconScriptsOnFirstPage.Count; ++i) + { + m_IconScriptsOnFirstPage[i].ResetState(); + } + for (int i = 0; i < m_IconScriptsOnNormalPage.Count; ++i) + { + m_IconScriptsOnNormalPage[i].ResetState(); + } + if (m_NewSketchButtonScript) + { + m_NewSketchButtonScript.ResetState(); + } + if (m_PaintButtonScript) + { + m_PaintButtonScript.ResetState(); + } + } + else if (m_CurrentState == PanelState.Available) + { + m_OnlineGalleryButtonRenderer.material.SetFloat("_Grayscale", 0); + m_ProfileButtonRenderer.material.SetFloat("_Grayscale", 0); + m_SketchSet.RequestRefresh(); + } + } + + override protected void OnUpdateGazeBehavior(Color rPanelColor) + { + // Set the appropriate dim value for all our buttons and sliders + if (Icons != null) + { + foreach (BaseButton icon in Icons) + { + icon.SetColor(rPanelColor); + } + } + + if (m_NewSketchButtonScript != null) + { + m_NewSketchButtonScript.SetColor(rPanelColor); + } + + if (m_NavigationButtons != null) + { + for (int i = 0; i < m_NavigationButtons.Length; ++i) + { + m_NavigationButtons[i].SetColor(rPanelColor); + } + } + } + + override public bool RaycastAgainstMeshCollider(Ray rRay, out RaycastHit rHitInfo, float fDist) + { + if (m_NewSketchButton.GetComponent().Raycast(rRay, out rHitInfo, fDist)) + { + return true; + } + return base.RaycastAgainstMeshCollider(rRay, out rHitInfo, fDist); + } + + // Works specifically with GalleryButtons. + public void ButtonPressed(GalleryButton.Type rType, BaseButton button = null) + { + switch (rType) + { + case GalleryButton.Type.Exit: + SketchSurfacePanel.m_Instance.EnableDefaultTool(); + PointerManager.m_Instance.EatLineEnabledInput(); + break; + case GalleryButton.Type.Showcase: + SetVisibleSketchSet(SketchSetType.Curated); + break; + case GalleryButton.Type.Local: + SetVisibleSketchSet(SketchSetType.User); + break; + case GalleryButton.Type.Liked: + SetVisibleSketchSet(SketchSetType.Liked); + break; + case GalleryButton.Type.Drive: + SetVisibleSketchSet(SketchSetType.Drive); + if (!m_ReadOnlyShown) + { + CreatePopUp(SketchControlsScript.GlobalCommands.ReadOnlyNotice, + -1, -1, m_ReadOnlyPopupOffset); + if (button != null) + { + button.ResetState(); + } + m_ReadOnlyShown = true; + } + break; + default: + break; + } + } + + private void OnSketchSetDirty() + { + ComputeNumPages(); + + SceneFileInfo first = (m_SketchSet.NumSketches > 0) ? + m_SketchSet.GetSketchSceneFileInfo(0) : null; + // If first sketch changed, return to first page. + if (m_FirstSketch != null && !m_FirstSketch.Equals(first)) + { + PageIndex = 0; + } + else + { + PageIndex = Mathf.Min(PageIndex, m_NumPages - 1); + } + m_FirstSketch = first; + GotoPage(PageIndex); + UpdateIndexOffset(); + RefreshPage(); + } + + override protected void UpdateIndexOffset() + { + m_IndexOffset = PageIndex == 0 ? 0 : m_IconsOnFirstPage.Length + (PageIndex - 1) * Icons.Count; + } + } +} // namespace TiltBrush diff --git a/Assets/Scripts/GUI/SketchesPanel.cs b/Assets/Scripts/GUI/SketchesPanel.cs index 7598c8e4bf..cce072b1cf 100644 --- a/Assets/Scripts/GUI/SketchesPanel.cs +++ b/Assets/Scripts/GUI/SketchesPanel.cs @@ -37,7 +37,7 @@ public override void InitPanel() base.InitPanel(); m_LastUploadProgress = -1.0f; - m_LoggedIn = App.GoogleIdentity.LoggedIn; + m_LoggedIn = App.GoogleIdentity.LoggedIn || App.IcosaIsLoggedIn; RefreshLoginButtonText(m_LoggedIn); } @@ -52,7 +52,7 @@ void Update() m_SaveOptionsButton.SetActive(alreadySaved); // Update share button's text. - bool loggedIn = App.GoogleIdentity.LoggedIn; + bool loggedIn = App.GoogleIdentity.LoggedIn || App.IcosaIsLoggedIn; if (loggedIn != m_LoggedIn) { RefreshLoginButtonText(loggedIn); diff --git a/Assets/Scripts/ImportGltfast.cs b/Assets/Scripts/ImportGltfast.cs index a557a83ff2..25a926d9f5 100644 --- a/Assets/Scripts/ImportGltfast.cs +++ b/Assets/Scripts/ImportGltfast.cs @@ -131,6 +131,7 @@ private static async Task _ImportUsingUnityGltf( catch (Exception e) { Debug.LogError("Failed to import using UnityGltf. Falling back to legacy import"); + Debug.LogError($"UnityGltf Exception: {e}"); // Fall back to the older import code GameObject go = _ImportUsingLegacyGltf(localPath, assetLocation); model.CalcBoundsGltf(go); diff --git a/Assets/Scripts/InputManager.cs b/Assets/Scripts/InputManager.cs index e0b898a0fe..c66b3c8d01 100644 --- a/Assets/Scripts/InputManager.cs +++ b/Assets/Scripts/InputManager.cs @@ -312,6 +312,8 @@ public struct TouchInput private Dictionary m_SketchToKeyboardCommandMap = new Dictionary(); + private bool m_DisableKeyboardShortcuts = false; + // // Public properties // @@ -383,6 +385,18 @@ public bool WandOnRight } } + public bool DisableKeyboardShortcuts + { + get + { + return m_DisableKeyboardShortcuts; + } + set + { + m_DisableKeyboardShortcuts = value; + } + } + public void EnablePoseTracking(bool enabled) { UnityEngine.XR.XRDevice.DisableAutoXRCameraTracking(App.VrSdk.GetVrCamera(), !enabled); @@ -532,6 +546,7 @@ void OnControllerPosesApplied() public bool GetKeyboardShortcut(KeyboardShortcut shortcut) { + if (m_DisableKeyboardShortcuts) return false; if (!ActiveKeyMap.TryGetValue((int)shortcut, out Key[] codes)) { return false; @@ -548,6 +563,7 @@ public bool GetKeyboardShortcut(KeyboardShortcut shortcut) public bool GetKeyboardShortcutDown(KeyboardShortcut shortcut) { + if (m_DisableKeyboardShortcuts) return false; if (!ActiveKeyMap.TryGetValue((int)shortcut, out Key[] codes)) { return false; diff --git a/Assets/Scripts/Model.cs b/Assets/Scripts/Model.cs index f913957b05..f6537790e0 100644 --- a/Assets/Scripts/Model.cs +++ b/Assets/Scripts/Model.cs @@ -1,961 +1,1028 @@ -// Copyright 2020 The Tilt Brush Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// 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 System; -using System.Collections; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Threading.Tasks; -using TiltBrushToolkit; -using Unity.VectorGraphics; -using Debug = UnityEngine.Debug; -using UObject = UnityEngine.Object; - - -namespace TiltBrush -{ - - public class Model - { - public struct Location - { - public enum Type - { - Invalid, - LocalFile, - PolyAssetId - } - - private Type type; - private string path; - private string id; // Only valid when the type is PolyAssetId. - - public static Location File(string relativePath) - { - int lastIndex = relativePath.LastIndexOf('#'); - string path, fragment; - - if (lastIndex == -1) - { - path = relativePath; - fragment = null; - } - else - { - path = relativePath.Substring(0, lastIndex); - fragment = relativePath.Substring(lastIndex + 1); - } - return new Location - { - type = Type.LocalFile, - path = path, - }; - } - - public static Location PolyAsset(string assetId, string path) - { - return new Location - { - type = Type.PolyAssetId, - path = path, - id = assetId - }; - } - - /// Can return null if this is a location for a fake Model (like the ones ModelWidget - /// assigns itself while the real Model content is in progress of being loaded). - public string AbsolutePath - { - get - { - if (path == null) - { - return null; - } - switch (type) - { - case Type.LocalFile: - return Path.Combine(App.ModelLibraryPath(), path).Replace("\\", "/"); - case Type.PolyAssetId: - return path.Replace("\\", "/"); - } - return null; - } - } - - public string RelativePath - { - get - { - if (type == Type.LocalFile) { return path; } - throw new Exception("Invalid relative path request"); - } - } - - public string Extension => Path.GetExtension(AbsolutePath).ToLower(); - - public string AssetId - { - get - { - if (type == Type.PolyAssetId) { return id; } - throw new Exception("Invalid Poly asset id request"); - } - } - - public Type GetLocationType() { return type; } - - public override int GetHashCode() - { - return this.ToString().GetHashCode(); - } - - public override string ToString() - { - string str; - if (type == Type.PolyAssetId) - { - str = $"{type}:{id}"; - } - else - { - str = $"{type}:{path}"; - } - return str; - } - - public override bool Equals(object obj) - { - if (!(obj is Location)) - { - return false; - } - return this == (Location)obj; - } - - public static bool operator ==(Location a, Location b) - { - return a.type == b.type && a.path == b.path; - } - - public static bool operator !=(Location a, Location b) - { - return !(a == b); - } - } - - private static readonly float kMeshMsPerFrame = 1.0f; - - private static readonly GltfImportOptions kPolyGltfImportOptions = new GltfImportOptions - { - rescalingMode = GltfImportOptions.RescalingMode.CONVERT, - scaleFactor = App.METERS_TO_UNITS, - axisConventionOverride = AxisConvention.kGltfAccordingToPoly, - recenter = false - }; - - private static readonly GltfImportOptions kGltfImportOptions = new GltfImportOptions - { - rescalingMode = GltfImportOptions.RescalingMode.CONVERT, - scaleFactor = App.METERS_TO_UNITS, - recenter = false - }; - - static RateLimiter sm_Limiter = new RateLimiter(maxEventsPerFrame: 1); - - // This is the object that is cloned when attached to a button or widget. - // It is the object that contains ObjModelScript. - public Transform m_ModelParent; - public Bounds m_MeshBounds; - - // Data & properties associated with current the state: - // - Unloaded - // - Trying to be loaded - // - Load finished successfully - // - Load finished unsuccessfully - // Not all of these states are modeled explicitly; this is a WIP. - - public struct LoadError - { - public LoadError(string message, string detail = null) - { - this.message = message; - this.detail = detail; - } - public readonly string message; // Human-readable short message - public readonly string detail; // Maybe non-human-readable details - // maybe? public bool transient; // true if we know for sure that this error is transient - } - - /// Is m_ModelParent assigned? - /// m_Valid = true implies m_LoadError == null - public bool m_Valid; - - /// m_LoadError != null implies m_Valid == false - private LoadError? m_LoadError; - public LoadError? Error => m_LoadError; - - // How many widgets are using this model? - public int m_UsageCount; - - private Location m_Location; - - // Can the geometry in this model be exported. - private bool m_AllowExport; - - private ImportMaterialCollector m_ImportMaterialCollector; - - // Returns the path starting after Media Library/Models - // e.g. subdirectory/example.obj - public string RelativePath - { - get { return m_Location.RelativePath; } - } - - public string AssetId - { - get { return m_Location.AssetId; } - } - - public string HumanName - { - get { return Path.GetFileNameWithoutExtension(m_Location.RelativePath); } - } - - public bool AllowExport - { - get { return m_AllowExport; } - } - - /// Only allowed if AllowExport = true - public IExportableMaterial GetExportableMaterial(Material material) - { - EnsureCollectorExists(); - return m_ImportMaterialCollector.GetExportableMaterial(material); - } - - public Model(Location location) - { - m_Location = location; - } - - public Location GetLocation() { return m_Location; } - - /// A helper class which allows import to run I/O on a background thread before producing Unity - /// GameObject(s). Usage: - /// BeginAsyncLoad() - /// TryEndAsyncLoad() repeat until it returns true; a bit of work is done each time(*) - /// CancelAsyncLoad() if you give up waiting for it to return true - /// - /// (*) Although the caller appears to have the responsibility of a scheduler, ModelBuilder - /// actually implements its own rate-limiting. After a set number of calls to TryEndAsyncLoad - /// in one frame (whether on one or many objects), further calls will be very fast no-ops. - /// So the caller can be (should be) a naive, performance-unaware scheduler that creates and - /// pumps as many ModelBuilders as it likes. - /// - /// However, note that this does not apply to the background-thread work. Nothing managages - /// that, so if N ModelBuilders are instantiated, N background threads will start running - /// and competing with each other. Your implementation may want to restrict that work to I/O. - abstract class ModelBuilder - { - protected string m_localPath; - private Future m_stateReader; - private IEnumerator m_meshEnumerator; - private ImportMaterialCollector m_ImportMaterialCollector; - private GameObject m_root; - - /// In the current implementation: - /// Before the first call to TryEndAsyncLoad, do not look at IsValid. - /// After the first call to TryEndAsyncLoad, IsValid is always true. - /// - /// TODO: semantics of IsValid = false are unclear and DoUnityThreadWork looks buggy - /// It's unclear if the intent is that the user should continue calling TryEndAsyncLoad - /// until it returns true, or if they should stop calling TryEndAsyncLoad. etc. Probably - /// we should remove this. - public bool IsValid - { - get; - protected set; - } - - public ModelBuilder(string localPath) - { - m_localPath = localPath; - IsValid = false; - } - - public void BeginAsyncLoad() - { - if (m_stateReader != null) - { - throw new ApplicationException("BeginImport should only be called once."); - } - - m_stateReader = new Future(DoBackgroundThreadWork, id => id.Dispose()); - } - - public void CancelAsyncLoad() - { - // If we have already created a mesh, we need to destroy it and the gameobject it is on so - // that we don't leave it orphaned in the heirarchy, and we don't leak meshes. - if (m_root != null) - { - foreach (var mesh in m_root.GetComponentsInChildren() - .Select(x => x.sharedMesh)) - { - UObject.Destroy(mesh); - } - UObject.Destroy(m_root); - m_root = null; - } - m_stateReader.Close(); - } - - /// Returns: - /// bool - false if incomplete, true upon successful completion. - /// GameObject - caller should check output GameObject to determine success. - /// ImportMaterialCollector - non-null upon successful completion. - /// Raises an exception on unsuccessful completion. - public bool TryEndAsyncLoad(out GameObject root, - out ImportMaterialCollector importMaterialCollector) - { - // Three things happen in this function. - // 1: It waits to try and get the result of reading the model on a background thread - // 2: It checks the rate limiter to make sure we don't have too many of these going on at once. - // 3: It enumerates through, creating meshes for the model. These are time-limited so that - // it will stop if it has taken too long in a single frame. - root = null; - importMaterialCollector = null; - if (m_meshEnumerator == null) - { - IDisposable state; - if (!m_stateReader.TryGetResult(out state)) { return false; } - - IEnumerable enumerable; - m_root = DoUnityThreadWork(state, out enumerable, out m_ImportMaterialCollector); - // TODO: Possible bugs if DoUnityThreadWork ever did fail: - // We assume the invariant that (root == null) == (IsValid == false) - // We assume the invariant that m_ImportMaterialCollector != null - // We don't dispose the GameObject or the enumerable - // If the user calls TryEndAsyncLoad again we might try to call DoUnityThreadWork again - if (m_root == null) - { - return false; - } - m_ImportMaterialCollector = new ImportMaterialCollector( - Path.GetDirectoryName(m_localPath), - uniqueSeed: m_localPath - ); - m_meshEnumerator = enumerable.GetEnumerator(); - m_root.SetActive(false); - } - // Yield until the limiter unblocks. - // Multiple calls to TryGetResult above are harmless. - if (sm_Limiter.IsBlocked()) - { - return false; - } - - // Finish constructing the actual game object. - Stopwatch stopwatch = new Stopwatch(); - stopwatch.Start(); - long numTicks = (long)((Stopwatch.Frequency * kMeshMsPerFrame) / 1000); - while (true) - { - if (!m_meshEnumerator.MoveNext()) - { - m_root.SetActive(true); - root = m_root; - importMaterialCollector = m_ImportMaterialCollector; - stopwatch.Stop(); - return true; - } - if (stopwatch.ElapsedTicks > numTicks) - { - stopwatch.Stop(); - return false; - } - } - } - - // Performs whatever of the import process that can happen on a non-Unity thread. - // Returns: - // disposable - passed to DoUnityThreadWork, or disposed of if the load is canceled. - protected abstract IDisposable DoBackgroundThreadWork(); - - // Performs whatever portion of the import process that is left. - // - // Pass: - // state - the value returned from DoBackgroundThreadWork. Ownership is transferred; - // callee is responsible for Disposing it. - // Returns: - // GameObject - the root of the object hierarchy. - // ImportMaterialCollector - the materials that were created, and info about them - // IEnumerable - a coroutine that will be pumped to completion - protected abstract GameObject DoUnityThreadWork( - IDisposable state, - out IEnumerable meshCreator, - out ImportMaterialCollector importMaterialCollector); - } - - /// The glTF ModelBuilder. - class GltfModelBuilder : ModelBuilder - { - private readonly bool m_useThreadedImageLoad; - private readonly bool m_fromPoly; - - public GltfModelBuilder(Location location, bool useThreadedImageLoad) - : base(location.AbsolutePath) - { - m_useThreadedImageLoad = useThreadedImageLoad; - m_fromPoly = (location.GetLocationType() == Location.Type.PolyAssetId); - } - - protected override IDisposable DoBackgroundThreadWork() - { - var loader = new TiltBrushUriLoader( - m_localPath, Path.GetDirectoryName(m_localPath), m_useThreadedImageLoad); - var options = m_fromPoly ? kPolyGltfImportOptions : kGltfImportOptions; - return NewGltfImporter.BeginImport(m_localPath); - } - - protected override GameObject DoUnityThreadWork(IDisposable state__, - out IEnumerable meshEnumerable, - out ImportMaterialCollector - importMaterialCollector) - { - meshEnumerable = null; - importMaterialCollector = null; - GameObject rootObject = null; - using (IDisposable state_ = state__) - { - var state = state_ as NewGltfImporter.ImportState; - if (state != null) - { - string assetLocation = Path.GetDirectoryName(m_localPath); - // EndImport doesn't try to use the loadImages functionality of UriLoader anyway. - // It knows it's on the main thread, so chooses to use Unity's fast loading. - rootObject = state.root; - importMaterialCollector = new ImportMaterialCollector(assetLocation, uniqueSeed: m_localPath); - } - } - IsValid = rootObject != null; - return rootObject; - } - } // GltfModelBuilder - - GameObject LoadUsd(List warnings) - { -#if USD_SUPPORTED - return ImportUsd.Import(m_Location.AbsolutePath, out warnings); -#endif - m_LoadError = new LoadError("usd not supported"); - return null; - } - - GameObject LoadPly(List warningsOut) - { - - try - { - var reader = new PlyReader(m_Location.AbsolutePath); - var (gameObject, warnings, collector) = reader.Import(); - warningsOut.AddRange(warnings); - m_ImportMaterialCollector = collector; - m_AllowExport = (m_ImportMaterialCollector != null); - return gameObject; - } - catch (Exception ex) - { - m_LoadError = new LoadError("Invalid data", ex.Message); - m_AllowExport = false; - Debug.LogException(ex); - return null; - } - - } - - GameObject LoadSvg(List warningsOut, out SVGParser.SceneInfo sceneInfo) - { - try - { - var reader = new SvgMeshReader(m_Location.AbsolutePath); - var (gameObject, warnings, collector, si) = reader.Import(); - sceneInfo = si; - warningsOut.AddRange(warnings); - m_ImportMaterialCollector = collector; - m_AllowExport = (m_ImportMaterialCollector != null); - return gameObject; - } - catch (Exception ex) - { - m_LoadError = new LoadError("Invalid data", ex.Message); - m_AllowExport = false; - Debug.LogException(ex); - sceneInfo = new SVGParser.SceneInfo(); - return null; - } - } - - /// Load model using FBX SDK. - GameObject LoadFbx(List warningsOut) - { -#if !FBX_SUPPORTED - m_LoadError = new LoadError("fbx not supported"); - return null; -#else - try - { - var reader = new FbxReader(m_Location.AbsolutePath); - var (gameObject, warnings, collector) = reader.Import(); - warningsOut.AddRange(warnings); - m_ImportMaterialCollector = collector; - m_AllowExport = (m_ImportMaterialCollector != null); - return gameObject; - } - catch (Exception ex) - { - m_LoadError = new LoadError("Invalid data", ex.Message); - m_AllowExport = false; - Debug.LogException(ex); - return null; - } -#endif - } - - async Task LoadGltf(List warnings) - { - string localPath = m_Location.AbsolutePath; - string assetLocation = Path.GetDirectoryName(localPath); - try - { - Task t = NewGltfImporter.StartSyncImport( - localPath, - assetLocation, - this, - warnings - ); - m_AllowExport = true; - await t; - } - catch (Exception ex) - { - m_AllowExport = false; - m_LoadError = new LoadError("Invalid data", ex.Message); - Debug.LogException(ex); - } - } - - private ModelBuilder m_builder; - - public void CancelLoadModelAsync() - { - if (m_builder != null) - { - m_builder.CancelAsyncLoad(); - m_builder = null; - } - } - - /// Threaded image loading is slower, but won't block the main thread. - /// If you're running in compositor and don't care about hitching, better to turn it off. - public void LoadModelAsync(bool useThreadedImageLoad) - { - if (m_builder != null) - { - throw new ApplicationException("Load in progress"); - } - - bool allowUsd = false; -#if USD_SUPPORTED - allowUsd = true; -#endif - - // Experimental usd loading. - if (allowUsd && - m_Location.GetLocationType() == Location.Type.LocalFile && - m_Location.Extension == ".usd") - { - throw new NotImplementedException(); - } - else if (m_Location.GetLocationType() == Location.Type.PolyAssetId) - { - // If we pulled this from Poly, it's going to be a gltf file. - m_builder = new GltfModelBuilder(m_Location, useThreadedImageLoad); - } - else - { - // Assume local files load with the FbxReader. - throw new NotImplementedException(); - } - - m_builder.BeginAsyncLoad(); - } - - public bool IsLoading() - { - return m_builder != null; - } - - /// For use in conjunction with LoadModelAsync(), returns true when the async load is complete, - /// false while still loading. - /// - /// Throws if called after async load is complete or before async load started. - /// When this returns, the Model will be either Valid, or LoadError will be set. - public bool TryLoadModel() - { - GameObject go = null; - bool isValid = false; - LoadError? error = null; - try - { - if (!m_builder.TryEndAsyncLoad(out go, out m_ImportMaterialCollector)) - { - return false; - } - isValid = m_builder.IsValid; - } - catch (ObjectDisposedException ex) - { - // This is a bad exception, it means we closed the future before calling TryGetModel. - error = new LoadError("Internal error", ex.Message); - Debug.LogException(ex); - } - catch (FutureFailed ex) - { - // Something went wrong in the glTF loader on the background thread. - error = new LoadError("Invalid data", ex.InnerException?.Message); - Debug.LogException(ex); - // TODO: Temporary, for b/139759540 and b/134430318 - // Leave the other exception alone so our analytics get the aggregated results. - Debug.LogException( - new Exception(string.Format("Failed loading model {0}", m_Location), ex)); - } - - m_builder = null; - - if (!isValid) - { - m_LoadError = error ?? new LoadError("Unexpected Failure"); - } - else - { - m_AllowExport = go != null; - StartCreatePrefab(go); - } - - AssignMaterialsToCollector(m_ImportMaterialCollector); - - // Even if an exception occurs above, return true because the return value indicates async load - // is complete. - return true; - } - - public async Task LoadModelAsync() - { - Task t = StartCreatePrefab(null); - await t; - - } - public void LoadModel() - { - StartCreatePrefab(null); - - } - - /// Either synchronously load a GameObject hierarchy and convert it to a "prefab" - /// or take a previously (probably asynchronously-loaded) GameObject hierarchy and do the same. - /// - /// Sets m_ModelParent and m_MeshBounds. - /// - /// Requirements for the passed GameObject: - /// - Its transform is identity - /// - Every visible mesh also has a BoxCollider - /// - Every BoxCollider also has a visible mesh - private async Task StartCreatePrefab(GameObject go) - { - if (m_Valid) - { - // This case is handled properly but it seems wasteful. - Debug.LogWarning($"Replacing already-loaded {m_Location}: did you mean to?"); - } - - List warnings = new List(); - - // If we weren't provided a GameObject, construct one now. - if (go == null) - { - m_AllowExport = false; - // TODO: if it's not already null, why did we get here? Probably want to check for error - // and bail at a higher level, and require as a precondition that error == null - m_LoadError = null; - - string ext = m_Location.Extension; - if (m_Location.GetLocationType() == Location.Type.LocalFile && - ext == ".usd") - { - // Experimental usd loading. - go = LoadUsd(warnings); - CalcBoundsNonGltf(go); - EndCreatePrefab(go, warnings); - } - else if (m_Location.GetLocationType() == Location.Type.PolyAssetId || - ext == ".gltf2" || ext == ".gltf" || ext == ".glb") - { - // If we pulled this from Poly, it's going to be a gltf file. - Task t = LoadGltf(warnings); - await t; - } - else if (ext == ".fbx" || ext == ".obj") - { - go = LoadFbx(warnings); - CalcBoundsNonGltf(go); - EndCreatePrefab(go, warnings); - } - else if (ext == ".ply") - { - go = LoadPly(warnings); - CalcBoundsNonGltf(go); - EndCreatePrefab(go, warnings); - } - else if (ext == ".svg") - { - go = LoadSvg(warnings, out SVGParser.SceneInfo sceneInfo); - CalcBoundsNonGltf(go); - EndCreatePrefab(go, warnings); - go.GetComponent().SvgSceneInfo = sceneInfo; - } - else - { - m_LoadError = new LoadError("Unknown format", ext); - } - } - - } - - public void CalcBoundsGltf(GameObject go) - { - Bounds b = new Bounds(); - bool first = true; - var boundsList = go.GetComponentsInChildren().Select(x => x.bounds).ToList(); - var skinnedMeshRenderers = go.GetComponentsInChildren(); - boundsList.AddRange(skinnedMeshRenderers.Select(x => x.bounds)); - foreach (Bounds bounds in boundsList) - { - if (first) - { - b = bounds; - first = false; - } - else - { - b.Encapsulate(bounds); - } - } - m_MeshBounds = b; - if (first) - { - // There was no geometry - Debug.LogErrorFormat("No usable geometry in model. LoadModel({0})", go.name); - } - } - - private void CalcBoundsNonGltf(GameObject go) - { - // TODO: this list of colliders is assumed to match the modelScript.m_MeshChildren array - // This should be enforced. - - // bc.bounds is world-space; therefore this calculation requires that - // go.transform be identity - Debug.Assert(Coords.AsGlobal[go.transform] == TrTransform.identity); - Bounds b = new Bounds(); - bool first = true; - foreach (BoxCollider bc in go.GetComponentsInChildren()) - { - if (first) - { - b = new Bounds(bc.bounds.center, bc.bounds.size); - first = false; - } - else - { - b.Encapsulate(bc.bounds); - } - UnityEngine.Object.Destroy(bc); - } - m_MeshBounds = b; - if (first) - { - // There was no geometry - Debug.LogErrorFormat("No usable geometry in model. LoadModel({0})", go.name); - } - - } - - public void EndCreatePrefab(GameObject go, List warnings) - { - if (go == null) - { - m_LoadError = m_LoadError ?? new LoadError("Bad data"); - DisplayWarnings(warnings); - } - - // Adopt the GameObject - go.name = m_Location.ToString(); - go.AddComponent().Init(); - go.SetActive(false); - if (m_ModelParent != null) - { - UnityEngine.Object.Destroy(m_ModelParent.gameObject); - } - m_ModelParent = go.transform; - - // !!! Add to material dictionary here? - - m_Valid = true; - DisplayWarnings(warnings); - - } - - public void UnloadModel() - { - if (m_builder != null) - { - m_builder.CancelAsyncLoad(); - m_builder = null; - } - m_Valid = false; - m_LoadError = null; - if (m_ModelParent != null) - { - // Procedurally created meshes need to be explicitly destroyed - you can't just destroy - // the MeshFilter that references them. - foreach (var mesh in m_ModelParent.GetComponentsInChildren() - .Select(x => x.sharedMesh)) - { - UObject.Destroy(mesh); - } - UObject.Destroy(m_ModelParent.gameObject); - m_ModelParent = null; - } - } - - /// Resets this.Error and tries to load the model again. - /// Pass the reason the Model is being pulled into memory, for logging purposes. - /// - /// When this coroutine terminates, you are guaranteed that m_Valid == true - /// or m_LoadError != null. - public IEnumerator LoadFullyCoroutine(string reason) - { - m_LoadError = null; - var type = m_Location.GetLocationType(); - switch (type) - { - case Location.Type.LocalFile: - yield return OverlayManager.m_Instance.RunInCompositor( - OverlayType.LoadModel, LoadModel, 0.25f); - break; - case Location.Type.PolyAssetId: - App.PolyAssetCatalog.RequestModelLoad(this, reason); - yield return null; - while (!m_Valid && !m_LoadError.HasValue) - { - yield return null; - } - break; - default: - m_LoadError = new LoadError($"Unknown load type {type}"); - break; - } - } - - private void DisplayWarnings(List warnings) - { - if (warnings.Count > 0) - { - TiltBrush.ControllerConsoleScript.m_Instance.AddNewLine( - "Loading " + Path.GetFileName(m_Location.AbsolutePath), true); - foreach (string warning in warnings) - { - TiltBrush.ControllerConsoleScript.m_Instance.AddNewLine( - OutputWindowScript.GetShorterFileName(warning.Replace("/", @"\")), false); - } - } - } - - public bool IsCached() - { - return m_Location.GetLocationType() == Location.Type.PolyAssetId && - Directory.Exists(m_Location.AbsolutePath); - } - - public void RefreshCache() - { - Directory.SetLastAccessTimeUtc( - Path.GetDirectoryName(m_Location.AbsolutePath), System.DateTime.UtcNow); - } - - // Returns all leaf meshes which are part of the model. - // Analagous to ModelWidget.GetMeshes(). - // Do not mutate the return value. - public MeshFilter[] GetMeshes() - { - if (!m_Valid) - { - throw new InvalidOperationException(); - } - return m_ModelParent.GetComponent().m_MeshChildren; - } - - public string GetExportName() - { - switch (GetLocation().GetLocationType()) - { - case Model.Location.Type.LocalFile: - return Path.GetFileNameWithoutExtension(RelativePath); - case Model.Location.Type.PolyAssetId: - return AssetId; - } - return "Unknown"; - } - - public void AssignMaterialsToCollector(ImportMaterialCollector collector) - { - m_ImportMaterialCollector = collector; - foreach (var mf in GetMeshes()) - { - foreach (var unityMat in mf.GetComponent().materials) - { - m_ImportMaterialCollector.Add(unityMat); - } - } - } - - public void EnsureCollectorExists() - { - if (m_ImportMaterialCollector == null) - { - var localPath = GetLocation().AbsolutePath; - m_ImportMaterialCollector = new ImportMaterialCollector( - Path.GetDirectoryName(localPath), - uniqueSeed: localPath - ); - AssignMaterialsToCollector(m_ImportMaterialCollector); - } - } - } -} // namespace TiltBrush; +// Copyright 2020 The Tilt Brush Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// 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 System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using TiltBrushToolkit; +using Unity.Profiling; +using Unity.VectorGraphics; +using Debug = UnityEngine.Debug; +using UObject = UnityEngine.Object; + + +namespace TiltBrush +{ + + public class Model + { + public struct Location + { + public enum Type + { + Invalid, + LocalFile, + IcosaAssetId + } + + private Type type; + private string path; + private string id; // Only valid when the type is IcosaAssetId. + + public static Location File(string relativePath) + { + int lastIndex = relativePath.LastIndexOf('#'); + string path, fragment; + + if (lastIndex == -1) + { + path = relativePath; + fragment = null; + } + else + { + path = relativePath.Substring(0, lastIndex); + fragment = relativePath.Substring(lastIndex + 1); + } + return new Location + { + type = Type.LocalFile, + path = path, + }; + } + + public static Location IcosaAsset(string assetId, string path) + { + return new Location + { + type = Type.IcosaAssetId, + path = path, + id = assetId + }; + } + + /// Can return null if this is a location for a fake Model (like the ones ModelWidget + /// assigns itself while the real Model content is in progress of being loaded). + public string AbsolutePath + { + get + { + if (path == null) + { + return null; + } + switch (type) + { + case Type.LocalFile: + return Path.Combine(App.ModelLibraryPath(), path).Replace("\\", "/"); + case Type.IcosaAssetId: + return path.Replace("\\", "/"); + } + return null; + } + } + + public string RelativePath + { + get + { + if (type == Type.LocalFile) { return path; } + throw new Exception("Invalid relative path request"); + } + } + + public string Extension => Path.GetExtension(AbsolutePath).ToLower(); + + public string AssetId + { + get + { + if (type == Type.IcosaAssetId) { return id; } + throw new Exception("Invalid Icosa asset id request"); + } + } + + public Type GetLocationType() { return type; } + + public override int GetHashCode() + { + return this.ToString().GetHashCode(); + } + + public override string ToString() + { + string str; + if (type == Type.IcosaAssetId) + { + str = $"{type}:{id}"; + } + else + { + str = $"{type}:{path}"; + } + return str; + } + + public override bool Equals(object obj) + { + if (!(obj is Location)) + { + return false; + } + return this == (Location)obj; + } + + public static bool operator ==(Location a, Location b) + { + return a.type == b.type && a.path == b.path; + } + + public static bool operator !=(Location a, Location b) + { + return !(a == b); + } + } + + private static readonly float kMeshMsPerFrame = 1.0f; + + private static readonly GltfImportOptions kPolyGltfImportOptions = new GltfImportOptions + { + rescalingMode = GltfImportOptions.RescalingMode.CONVERT, + scaleFactor = App.METERS_TO_UNITS, + axisConventionOverride = AxisConvention.kGltfAccordingToIcosa, + recenter = false + }; + + private static readonly GltfImportOptions kGltfImportOptions = new GltfImportOptions + { + rescalingMode = GltfImportOptions.RescalingMode.CONVERT, + scaleFactor = App.METERS_TO_UNITS, + recenter = false + }; + + static RateLimiter sm_Limiter = new RateLimiter(maxEventsPerFrame: 1); + + // This is the object that is cloned when attached to a button or widget. + // It is the object that contains ObjModelScript. + public Transform m_ModelParent; + public Bounds m_MeshBounds; + + // Data & properties associated with current the state: + // - Unloaded + // - Trying to be loaded + // - Load finished successfully + // - Load finished unsuccessfully + // Not all of these states are modeled explicitly; this is a WIP. + + public struct LoadError + { + public LoadError(string message, string detail = null) + { + this.message = message; + this.detail = detail; + } + public readonly string message; // Human-readable short message + public readonly string detail; // Maybe non-human-readable details + // maybe? public bool transient; // true if we know for sure that this error is transient + } + + /// Is m_ModelParent assigned? + /// m_Valid = true implies m_LoadError == null + public bool m_Valid; + + /// m_LoadError != null implies m_Valid == false + private LoadError? m_LoadError; + public LoadError? Error => m_LoadError; + + // How many widgets are using this model? + public int m_UsageCount; + + private Location m_Location; + + // Can the geometry in this model be exported. + private bool m_AllowExport; + + private ImportMaterialCollector m_ImportMaterialCollector; + + // Returns the path starting after Media Library/Models + // e.g. subdirectory/example.obj + public string RelativePath + { + get { return m_Location.RelativePath; } + } + + public string AssetId + { + get { return m_Location.AssetId; } + } + + public string HumanName + { + get { return Path.GetFileNameWithoutExtension(m_Location.RelativePath); } + } + + public bool AllowExport + { + get { return m_AllowExport; } + } + + /// Only allowed if AllowExport = true + public IExportableMaterial GetExportableMaterial(Material material) + { + EnsureCollectorExists(); + return m_ImportMaterialCollector.GetExportableMaterial(material); + } + + public Model(Location location) + { + m_Location = location; + } + + public Location GetLocation() { return m_Location; } + + /// A helper class which allows import to run I/O on a background thread before producing Unity + /// GameObject(s). Usage: + /// BeginAsyncLoad() + /// TryEndAsyncLoad() repeat until it returns true; a bit of work is done each time(*) + /// CancelAsyncLoad() if you give up waiting for it to return true + /// + /// (*) Although the caller appears to have the responsibility of a scheduler, ModelBuilder + /// actually implements its own rate-limiting. After a set number of calls to TryEndAsyncLoad + /// in one frame (whether on one or many objects), further calls will be very fast no-ops. + /// So the caller can be (should be) a naive, performance-unaware scheduler that creates and + /// pumps as many ModelBuilders as it likes. + /// + /// However, note that this does not apply to the background-thread work. Nothing managages + /// that, so if N ModelBuilders are instantiated, N background threads will start running + /// and competing with each other. Your implementation may want to restrict that work to I/O. + abstract class ModelBuilder + { + protected string m_localPath; + private Future m_stateReader; + private IEnumerator m_meshEnumerator; + private ImportMaterialCollector m_ImportMaterialCollector; + private GameObject m_root; + + /// In the current implementation: + /// Before the first call to TryEndAsyncLoad, do not look at IsValid. + /// After the first call to TryEndAsyncLoad, IsValid is always true. + /// + /// TODO: semantics of IsValid = false are unclear and DoUnityThreadWork looks buggy + /// It's unclear if the intent is that the user should continue calling TryEndAsyncLoad + /// until it returns true, or if they should stop calling TryEndAsyncLoad. etc. Probably + /// we should remove this. + public bool IsValid + { + get; + protected set; + } + + public ModelBuilder(string localPath) + { + m_localPath = localPath; + IsValid = false; + } + + public void BeginAsyncLoad() + { + if (m_stateReader != null) + { + throw new ApplicationException("BeginImport should only be called once."); + } + + m_stateReader = new Future(DoBackgroundThreadWork, id => id.Dispose()); + } + + public void CancelAsyncLoad() + { + // If we have already created a mesh, we need to destroy it and the gameobject it is on so + // that we don't leave it orphaned in the heirarchy, and we don't leak meshes. + if (m_root != null) + { + foreach (var mesh in m_root.GetComponentsInChildren() + .Select(x => x.sharedMesh)) + { + UObject.Destroy(mesh); + } + UObject.Destroy(m_root); + m_root = null; + } + m_stateReader.Close(); + } + + /// Returns: + /// bool - false if incomplete, true upon successful completion. + /// GameObject - caller should check output GameObject to determine success. + /// ImportMaterialCollector - non-null upon successful completion. + /// Raises an exception on unsuccessful completion. + public bool TryEndAsyncLoad(out GameObject root, + out ImportMaterialCollector importMaterialCollector) + { + // Three things happen in this function. + // 1: It waits to try and get the result of reading the model on a background thread + // 2: It checks the rate limiter to make sure we don't have too many of these going on at once. + // 3: It enumerates through, creating meshes for the model. These are time-limited so that + // it will stop if it has taken too long in a single frame. + root = null; + importMaterialCollector = null; + if (m_meshEnumerator == null) + { + IDisposable state; + if (!m_stateReader.TryGetResult(out state)) { return false; } + + IEnumerable enumerable; + m_root = DoUnityThreadWork(state, out enumerable, out m_ImportMaterialCollector); + // TODO: Possible bugs if DoUnityThreadWork ever did fail: + // We assume the invariant that (root == null) == (IsValid == false) + // We assume the invariant that m_ImportMaterialCollector != null + // We don't dispose the GameObject or the enumerable + // If the user calls TryEndAsyncLoad again we might try to call DoUnityThreadWork again + if (m_root == null) + { + return false; + } + m_ImportMaterialCollector = new ImportMaterialCollector( + Path.GetDirectoryName(m_localPath), + uniqueSeed: m_localPath + ); + m_meshEnumerator = enumerable.GetEnumerator(); + m_root.SetActive(false); + } + // Yield until the limiter unblocks. + // Multiple calls to TryGetResult above are harmless. + if (sm_Limiter.IsBlocked()) + { + return false; + } + + // Finish constructing the actual game object. + Stopwatch stopwatch = new Stopwatch(); + stopwatch.Start(); + long numTicks = (long)((Stopwatch.Frequency * kMeshMsPerFrame) / 1000); + while (true) + { + if (!m_meshEnumerator.MoveNext()) + { + m_root.SetActive(true); + root = m_root; + importMaterialCollector = m_ImportMaterialCollector; + stopwatch.Stop(); + return true; + } + if (stopwatch.ElapsedTicks > numTicks) + { + stopwatch.Stop(); + return false; + } + } + } + + // Performs whatever of the import process that can happen on a non-Unity thread. + // Returns: + // disposable - passed to DoUnityThreadWork, or disposed of if the load is canceled. + protected abstract IDisposable DoBackgroundThreadWork(); + + // Performs whatever portion of the import process that is left. + // + // Pass: + // state - the value returned from DoBackgroundThreadWork. Ownership is transferred; + // callee is responsible for Disposing it. + // Returns: + // GameObject - the root of the object hierarchy. + // ImportMaterialCollector - the materials that were created, and info about them + // IEnumerable - a coroutine that will be pumped to completion + protected abstract GameObject DoUnityThreadWork( + IDisposable state, + out IEnumerable meshCreator, + out ImportMaterialCollector importMaterialCollector); + } + + /// The glTF ModelBuilder. + class GltfModelBuilder : ModelBuilder + { + private readonly bool m_useThreadedImageLoad; + private readonly bool m_fromIcosa; + + public GltfModelBuilder(Location location, bool useThreadedImageLoad) + : base(location.AbsolutePath) + { + m_useThreadedImageLoad = useThreadedImageLoad; + m_fromIcosa = (location.GetLocationType() == Location.Type.IcosaAssetId); + } + + protected override IDisposable DoBackgroundThreadWork() + { + var loader = new TiltBrushUriLoader( + m_localPath, Path.GetDirectoryName(m_localPath), m_useThreadedImageLoad); + var options = m_fromIcosa ? kPolyGltfImportOptions : kGltfImportOptions; + if (m_fromIcosa) + { + return ImportGltf.BeginImport(m_localPath, loader, options); + } + return NewGltfImporter.BeginImport(m_localPath); + } + + protected override GameObject DoUnityThreadWork(IDisposable state__, + out IEnumerable meshEnumerable, + out ImportMaterialCollector + importMaterialCollector) + { + GameObject rootObject = null; + if (m_fromIcosa) + { + var state = state__ as ImportGltf.ImportState; + if (state != null) + { + string assetLocation = Path.GetDirectoryName(m_localPath); + // EndImport doesn't try to use the loadImages functionality of UriLoader anyway. + // It knows it's on the main thread, so chooses to use Unity's fast loading. + var loader = new TiltBrushUriLoader(m_localPath, assetLocation, loadImages: false); + ImportGltf.GltfImportResult result = + ImportGltf.EndImport( + state, loader, + new ImportMaterialCollector(assetLocation, uniqueSeed: m_localPath), + out meshEnumerable); + + if (result != null) + { + rootObject = result.root; + importMaterialCollector = (ImportMaterialCollector)result.materialCollector; + } + } + IsValid = rootObject != null; + meshEnumerable = null; + importMaterialCollector = null; + return rootObject; + } + else + { + meshEnumerable = null; + importMaterialCollector = null; + using (IDisposable state_ = state__) + { + var state = state_ as NewGltfImporter.ImportState; + if (state != null) + { + string assetLocation = Path.GetDirectoryName(m_localPath); + // EndImport doesn't try to use the loadImages functionality of UriLoader anyway. + // It knows it's on the main thread, so chooses to use Unity's fast loading. + rootObject = state.root; + importMaterialCollector = new ImportMaterialCollector(assetLocation, uniqueSeed: m_localPath); + } + } + IsValid = rootObject != null; + return rootObject; + } + } + } // GltfModelBuilder + + GameObject LoadUsd(List warnings) + { +#if USD_SUPPORTED + return ImportUsd.Import(m_Location.AbsolutePath, out warnings); +#endif + m_LoadError = new LoadError("usd not supported"); + return null; + } + + GameObject LoadPly(List warningsOut) + { + + try + { + var reader = new PlyReader(m_Location.AbsolutePath); + var (gameObject, warnings, collector) = reader.Import(); + warningsOut.AddRange(warnings); + m_ImportMaterialCollector = collector; + m_AllowExport = (m_ImportMaterialCollector != null); + return gameObject; + } + catch (Exception ex) + { + m_LoadError = new LoadError("Invalid data", ex.Message); + m_AllowExport = false; + Debug.LogException(ex); + return null; + } + + } + + GameObject LoadSvg(List warningsOut, out SVGParser.SceneInfo sceneInfo) + { + try + { + var reader = new SvgMeshReader(m_Location.AbsolutePath); + var (gameObject, warnings, collector, si) = reader.Import(); + sceneInfo = si; + warningsOut.AddRange(warnings); + m_ImportMaterialCollector = collector; + m_AllowExport = (m_ImportMaterialCollector != null); + return gameObject; + } + catch (Exception ex) + { + m_LoadError = new LoadError("Invalid data", ex.Message); + m_AllowExport = false; + Debug.LogException(ex); + sceneInfo = new SVGParser.SceneInfo(); + return null; + } + } + + /// Load model using FBX SDK. + GameObject LoadFbx(List warningsOut) + { +#if !FBX_SUPPORTED + m_LoadError = new LoadError("fbx not supported"); + return null; +#else + try + { + var reader = new FbxReader(m_Location.AbsolutePath); + var (gameObject, warnings, collector) = reader.Import(); + warningsOut.AddRange(warnings); + m_ImportMaterialCollector = collector; + m_AllowExport = (m_ImportMaterialCollector != null); + return gameObject; + } + catch (Exception ex) + { + m_LoadError = new LoadError("Invalid data", ex.Message); + m_AllowExport = false; + Debug.LogException(ex); + return null; + } +#endif + } + + async Task LoadGltf(List warnings) + { + string localPath = m_Location.AbsolutePath; + string assetLocation = Path.GetDirectoryName(localPath); + try + { + Task t = NewGltfImporter.StartSyncImport( + localPath, + assetLocation, + this, + warnings + ); + m_AllowExport = true; + await t; + } + catch (Exception ex) + { + m_AllowExport = false; + m_LoadError = new LoadError("Invalid data", ex.Message); + Debug.LogException(ex); + } + } + + private ModelBuilder m_builder; + + public void CancelLoadModelAsync() + { + if (m_builder != null) + { + m_builder.CancelAsyncLoad(); + m_builder = null; + } + } + + /// Threaded image loading is slower, but won't block the main thread. + /// If you're running in compositor and don't care about hitching, better to turn it off. + public void LoadModelAsync(bool useThreadedImageLoad) + { + if (m_builder != null) + { + throw new ApplicationException("Load in progress"); + } + + bool allowUsd = false; +#if USD_SUPPORTED + allowUsd = true; +#endif + + // Experimental usd loading. + if (allowUsd && + m_Location.GetLocationType() == Location.Type.LocalFile && + m_Location.Extension == ".usd") + { + throw new NotImplementedException(); + } + else if (m_Location.GetLocationType() == Location.Type.IcosaAssetId) + { + // If we pulled this from Icosa, it's going to be a gltf file. + m_builder = new GltfModelBuilder(m_Location, useThreadedImageLoad); + } + else + { + // Assume local files load with the FbxReader. + throw new NotImplementedException(); + } + + m_builder.BeginAsyncLoad(); + } + + public bool IsLoading() + { + return m_builder != null; + } + + /// For use in conjunction with LoadModelAsync(), returns true when the async load is complete, + /// false while still loading. + /// + /// Throws if called after async load is complete or before async load started. + /// When this returns, the Model will be either Valid, or LoadError will be set. + public bool TryLoadModel() + { + GameObject go = null; + bool isValid = false; + LoadError? error = null; + try + { + if (!m_builder.TryEndAsyncLoad(out go, out m_ImportMaterialCollector)) + { + return false; + } + isValid = m_builder.IsValid; + } + catch (ObjectDisposedException ex) + { + // This is a bad exception, it means we closed the future before calling TryGetModel. + error = new LoadError("Internal error", ex.Message); + Debug.LogException(ex); + } + catch (FutureFailed ex) + { + // Something went wrong in the glTF loader on the background thread. + error = new LoadError("Invalid data", ex.InnerException?.Message); + Debug.LogException(ex); + // TODO: Temporary, for b/139759540 and b/134430318 + // Leave the other exception alone so our analytics get the aggregated results. + Debug.LogException( + new Exception(string.Format("Failed loading model {0}", m_Location), ex)); + } + + m_builder = null; + + if (!isValid) + { + m_LoadError = error ?? new LoadError("Unexpected Failure"); + } + else + { + m_AllowExport = go != null; + StartCreatePrefab(go); + } + + AssignMaterialsToCollector(m_ImportMaterialCollector); + + // Even if an exception occurs above, return true because the return value indicates async load + // is complete. + return true; + } + + public async Task LoadModelAsync() + { + Task t = StartCreatePrefab(null); + await t; + + } + public void LoadModel() + { + StartCreatePrefab(null); + + } + + /// Either synchronously load a GameObject hierarchy and convert it to a "prefab" + /// or take a previously (probably asynchronously-loaded) GameObject hierarchy and do the same. + /// + /// Sets m_ModelParent and m_MeshBounds. + /// + /// Requirements for the passed GameObject: + /// - Its transform is identity + /// - Every visible mesh also has a BoxCollider + /// - Every BoxCollider also has a visible mesh + private async Task StartCreatePrefab(GameObject go) + { + if (m_Valid) + { + // This case is handled properly but it seems wasteful. + Debug.LogWarning($"Replacing already-loaded {m_Location}: did you mean to?"); + } + + List warnings = new List(); + + // If we weren't provided a GameObject, construct one now. + if (go == null) + { + m_AllowExport = false; + // TODO: if it's not already null, why did we get here? Probably want to check for error + // and bail at a higher level, and require as a precondition that error == null + m_LoadError = null; + + string ext = m_Location.Extension; + if (m_Location.GetLocationType() == Location.Type.LocalFile && + ext == ".usd") + { + // Experimental usd loading. + go = LoadUsd(warnings); + CalcBoundsNonGltf(go); + EndCreatePrefab(go, warnings); + } + else if (m_Location.GetLocationType() == Location.Type.IcosaAssetId || + ext == ".gltf2" || ext == ".gltf" || ext == ".glb") + { + // If we pulled this from Icosa, it's going to be a gltf file. + Task t = LoadGltf(warnings); + await t; + } + else if (ext == ".fbx" || ext == ".obj") + { + go = LoadFbx(warnings); + CalcBoundsNonGltf(go); + EndCreatePrefab(go, warnings); + } + else if (ext == ".ply") + { + go = LoadPly(warnings); + CalcBoundsNonGltf(go); + EndCreatePrefab(go, warnings); + } + else if (ext == ".svg") + { + go = LoadSvg(warnings, out SVGParser.SceneInfo sceneInfo); + CalcBoundsNonGltf(go); + EndCreatePrefab(go, warnings); + go.GetComponent().SvgSceneInfo = sceneInfo; + } + else + { + m_LoadError = new LoadError("Unknown format", ext); + } + } + + } + + public void CalcBoundsGltf(GameObject go) + { + Bounds b = new Bounds(); + bool first = true; + var boundsList = go.GetComponentsInChildren().Select(x => x.bounds).ToList(); + var skinnedMeshRenderers = go.GetComponentsInChildren(); + boundsList.AddRange(skinnedMeshRenderers.Select(x => x.bounds)); + foreach (Bounds bounds in boundsList) + { + if (first) + { + b = bounds; + first = false; + } + else + { + b.Encapsulate(bounds); + } + } + m_MeshBounds = b; + if (first) + { + // There was no geometry + Debug.LogErrorFormat("No usable geometry in model. LoadModel({0})", go.name); + } + } + + private void CalcBoundsNonGltf(GameObject go) + { + // TODO: this list of colliders is assumed to match the modelScript.m_MeshChildren array + // This should be enforced. + + // bc.bounds is world-space; therefore this calculation requires that + // go.transform be identity + Debug.Assert(Coords.AsGlobal[go.transform] == TrTransform.identity); + Bounds b = new Bounds(); + bool first = true; + foreach (BoxCollider bc in go.GetComponentsInChildren()) + { + if (first) + { + b = new Bounds(bc.bounds.center, bc.bounds.size); + first = false; + } + else + { + b.Encapsulate(bc.bounds); + } + UnityEngine.Object.Destroy(bc); + } + m_MeshBounds = b; + if (first) + { + // There was no geometry + Debug.LogErrorFormat("No usable geometry in model. LoadModel({0})", go.name); + } + + } + + public void EndCreatePrefab(GameObject go, List warnings) + { + if (go == null) + { + m_LoadError = m_LoadError ?? new LoadError("Bad data"); + DisplayWarnings(warnings); + } + + // Adopt the GameObject + go.name = m_Location.ToString(); + go.AddComponent().Init(); + go.SetActive(false); + if (m_ModelParent != null) + { + UnityEngine.Object.Destroy(m_ModelParent.gameObject); + } + m_ModelParent = go.transform; + +#if DEVELOPMENT_BUILD || UNITY_EDITOR + ProfilerMarker generateUniqueNamesPerfMarker = new ProfilerMarker("Model.GenerateUniqueNames"); + generateUniqueNamesPerfMarker.Begin(); +#endif + + GenerateUniqueNames(m_ModelParent); + +#if DEVELOPMENT_BUILD || UNITY_EDITOR + generateUniqueNamesPerfMarker.End(); +#endif + + // !!! Add to material dictionary here? + + m_Valid = true; + DisplayWarnings(warnings); + } + + + // This method is called when the model has been loaded and the node tree is available + // This method is necessary because (1) nodes in e.g glTF files don't need to have unique names + // and (2) there's code in at least ModelWidget that searches for specific nodes using node names + private static void GenerateUniqueNames(Transform rootNode) + { + void SetUniqueNameForNode(Transform node) + { + // GetInstanceID returns a unique ID for every GameObject during a runtime session + node.name += " uid: " + node.gameObject.GetInstanceID(); + + foreach (Transform child in node) + { + SetUniqueNameForNode(child); + } + } + + foreach (Transform child in rootNode) + { + SetUniqueNameForNode(child); + } + } + + public void UnloadModel() + { + if (m_builder != null) + { + m_builder.CancelAsyncLoad(); + m_builder = null; + } + m_Valid = false; + m_LoadError = null; + if (m_ModelParent != null) + { + // Procedurally created meshes need to be explicitly destroyed - you can't just destroy + // the MeshFilter that references them. + foreach (var mesh in m_ModelParent.GetComponentsInChildren() + .Select(x => x.sharedMesh)) + { + UObject.Destroy(mesh); + } + UObject.Destroy(m_ModelParent.gameObject); + m_ModelParent = null; + } + } + + /// Resets this.Error and tries to load the model again. + /// Pass the reason the Model is being pulled into memory, for logging purposes. + /// + /// When this coroutine terminates, you are guaranteed that m_Valid == true + /// or m_LoadError != null. + public IEnumerator LoadFullyCoroutine(string reason) + { + m_LoadError = null; + var type = m_Location.GetLocationType(); + switch (type) + { + case Location.Type.LocalFile: + yield return OverlayManager.m_Instance.RunInCompositor( + OverlayType.LoadModel, LoadModel, 0.25f); + break; + case Location.Type.IcosaAssetId: + App.IcosaAssetCatalog.RequestModelLoad(this, reason); + yield return null; + while (!m_Valid && !m_LoadError.HasValue) + { + yield return null; + } + break; + default: + m_LoadError = new LoadError($"Unknown load type {type}"); + break; + } + } + + private void DisplayWarnings(List warnings) + { + if (warnings.Count > 0) + { + TiltBrush.ControllerConsoleScript.m_Instance.AddNewLine( + "Loading " + Path.GetFileName(m_Location.AbsolutePath), true); + foreach (string warning in warnings) + { + TiltBrush.ControllerConsoleScript.m_Instance.AddNewLine( + OutputWindowScript.GetShorterFileName(warning.Replace("/", @"\")), false); + } + } + } + + public bool IsCached() + { + return m_Location.GetLocationType() == Location.Type.IcosaAssetId && + Directory.Exists(m_Location.AbsolutePath); + } + + public void RefreshCache() + { + Directory.SetLastAccessTimeUtc( + Path.GetDirectoryName(m_Location.AbsolutePath), System.DateTime.UtcNow); + } + + // Returns all leaf meshes which are part of the model. + // Analagous to ModelWidget.GetMeshes(). + // Do not mutate the return value. + public MeshFilter[] GetMeshes() + { + if (!m_Valid) + { + throw new InvalidOperationException(); + } + return m_ModelParent.GetComponent().m_MeshChildren; + } + + public string GetExportName() + { + switch (GetLocation().GetLocationType()) + { + case Model.Location.Type.LocalFile: + return Path.GetFileNameWithoutExtension(RelativePath); + case Model.Location.Type.IcosaAssetId: + return AssetId; + } + return "Unknown"; + } + + public void AssignMaterialsToCollector(ImportMaterialCollector collector) + { + m_ImportMaterialCollector = collector; + foreach (var mf in GetMeshes()) + { + foreach (var unityMat in mf.GetComponent().materials) + { + m_ImportMaterialCollector.Add(unityMat); + } + } + } + + public void EnsureCollectorExists() + { + if (m_ImportMaterialCollector == null) + { + var localPath = GetLocation().AbsolutePath; + m_ImportMaterialCollector = new ImportMaterialCollector( + Path.GetDirectoryName(localPath), + uniqueSeed: localPath + ); + AssignMaterialsToCollector(m_ImportMaterialCollector); + } + } + } +} // namespace TiltBrush; diff --git a/Assets/Scripts/PacDebugWindow.cs b/Assets/Scripts/PacDebugWindow.cs index 64b9960775..147c5d8bf0 100644 --- a/Assets/Scripts/PacDebugWindow.cs +++ b/Assets/Scripts/PacDebugWindow.cs @@ -1,102 +1,102 @@ -// Copyright 2020 The Tilt Brush Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// 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.Collections.Generic; -using System.Linq; -using UnityEngine; -using UnityEditor; - -namespace TiltBrush -{ - - public partial class PolyAssetCatalog - { - - private class DebugWindow : EditorWindow - { - [MenuItem("Open Brush/Poly Asset Catalog Debug Window")] - private static void OpenDebugWindow() => GetWindow(); - - private static string ToString(AssetGetter ag) - { - return $"{ag.Asset.Id} {(ag.IsCanceled ? 'c' : '-')} {(ag.IsReady ? 'r' : '-')}"; - } - - private static string ToString(ModelLoadRequest m) - { - return $"{m.AssetId} {m.Reason}"; - } - - private bool m_showActiveRequests; - private bool m_showRequestQueue; - private bool m_showLoadQueue; - - private void Update() - { - if (Application.isPlaying) - { - Repaint(); - } - } - - private void OnGUI() - { - if (!Application.isPlaying) - { - EditorGUILayout.HelpBox("Only works in Play Mode.", MessageType.Info); - return; - } - var pac = App.PolyAssetCatalog; - - DrawCollection(ref m_showActiveRequests, "Downloads", pac.m_ActiveRequests, ToString); - DrawCollection(ref m_showRequestQueue, "RequestLoadQueue", pac.m_RequestLoadQueue, ToString); - DrawCollection(ref m_showLoadQueue, "LoadQueue", pac.m_LoadQueue, ToString); - } - - private void DrawCollection( - ref bool state, string label, ICollection collection, Func toString, - bool sort = false) - { - string withCount = $"{label} : {collection.Count}"; - state = EditorGUILayout.ToggleLeft(withCount, state); - if (!state || collection.Count == 0) { return; } - int i = 0; - if (sort) - { - List strings = collection.Select(toString).ToList(); - strings.Sort(); - foreach (string elt in strings) - { - EditorGUILayout.LabelField(i.ToString(), elt); - i += 1; - } - } - else - { - foreach (T elt in collection) - { - EditorGUILayout.LabelField(i.ToString(), toString(elt)); - i += 1; - } - } - } - } // class DebugWindow - } // class PolyAssetCatalog - -} // namespace TiltBrush - -#endif +// Copyright 2020 The Tilt Brush Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// 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.Collections.Generic; +using System.Linq; +using UnityEngine; +using UnityEditor; + +namespace TiltBrush +{ + + public partial class IcosaAssetCatalog + { + + private class DebugWindow : EditorWindow + { + [MenuItem("Open Brush/Poly Asset Catalog Debug Window")] + private static void OpenDebugWindow() => GetWindow(); + + private static string ToString(AssetGetter ag) + { + return $"{ag.Asset.Id} {(ag.IsCanceled ? 'c' : '-')} {(ag.IsReady ? 'r' : '-')}"; + } + + private static string ToString(ModelLoadRequest m) + { + return $"{m.AssetId} {m.Reason}"; + } + + private bool m_showActiveRequests; + private bool m_showRequestQueue; + private bool m_showLoadQueue; + + private void Update() + { + if (Application.isPlaying) + { + Repaint(); + } + } + + private void OnGUI() + { + if (!Application.isPlaying) + { + EditorGUILayout.HelpBox("Only works in Play Mode.", MessageType.Info); + return; + } + var pac = App.IcosaAssetCatalog; + + DrawCollection(ref m_showActiveRequests, "Downloads", pac.m_ActiveRequests, ToString); + DrawCollection(ref m_showRequestQueue, "RequestLoadQueue", pac.m_RequestLoadQueue, ToString); + DrawCollection(ref m_showLoadQueue, "LoadQueue", pac.m_LoadQueue, ToString); + } + + private void DrawCollection( + ref bool state, string label, ICollection collection, Func toString, + bool sort = false) + { + string withCount = $"{label} : {collection.Count}"; + state = EditorGUILayout.ToggleLeft(withCount, state); + if (!state || collection.Count == 0) { return; } + int i = 0; + if (sort) + { + List strings = collection.Select(toString).ToList(); + strings.Sort(); + foreach (string elt in strings) + { + EditorGUILayout.LabelField(i.ToString(), elt); + i += 1; + } + } + else + { + foreach (T elt in collection) + { + EditorGUILayout.LabelField(i.ToString(), toString(elt)); + i += 1; + } + } + } + } // class DebugWindow + } // class PolyAssetCatalog + +} // namespace TiltBrush + +#endif diff --git a/Assets/Scripts/Poly/PolyAssetCatalog.cs b/Assets/Scripts/Poly/IcosaAssetCatalog.cs similarity index 91% rename from Assets/Scripts/Poly/PolyAssetCatalog.cs rename to Assets/Scripts/Poly/IcosaAssetCatalog.cs index 0bd1cda443..a2facd3977 100644 --- a/Assets/Scripts/Poly/PolyAssetCatalog.cs +++ b/Assets/Scripts/Poly/IcosaAssetCatalog.cs @@ -1,1006 +1,1011 @@ -// Copyright 2020 The Tilt Brush Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// 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 UnityEngine.Networking; -using System; -using System.Linq; -using System.Collections.Generic; -using System.IO; -using System.Text.RegularExpressions; -using Newtonsoft.Json.Linq; -using Newtonsoft.Json; - -namespace TiltBrush -{ - - /// Used as an accessor for files downloaded from Poly and cached on local storage. - public partial class PolyAssetCatalog : MonoBehaviour - { - const int kAssetDiskCacheSize = 1000; - const float kThumbnailFetchRate = 15; - const int kThumbnailFetchMaxCount = 30; - const int kThumbnailReadRate = 4; - - // This may be a bit broader than an asset id, but it's a safe set of - // filename characters. - // Change - added . % ~ to allow urlencoded urls - static readonly Regex sm_AssetIdPattern = new Regex(@"^[a-zA-Z0-9-_%~\.]+$"); - - public enum AssetLoadState - { - Unknown, - NotDownloaded, - Downloading, - Downloaded, // On disk but not in memory - // DownloadFailed, // We don't keep track of download errors, so this becomes "NotDownloaded" - Loading, - LoadFailed, // This shows up as a !Valid model in the model catalog - Loaded - } - - public class AssetDetails - { - // Disabled only because there isn't a pressing reason to enable it. - const bool kLazyLoadThumbnail = false; - - private readonly PolyAssetCatalog m_Owner; - private readonly Texture2D m_Thumbnail; - private string m_ThumbnailUrl; // if non-null, have not attempted to fetch it yet - - public string AssetId { get; } - public string HumanName { get; } - public string AccountName { get; } - public Quaternion? ModelRotation { get; } - - public Texture2D Thumbnail - { - get - { - if (m_ThumbnailUrl != null) - { - string url = m_ThumbnailUrl; - m_ThumbnailUrl = null; - DownloadThumbnailAsync(url); - } - return m_Thumbnail; - } - } - - public Model Model { get { return App.PolyAssetCatalog.GetModel(AssetId); } } - - public AssetDetails( - JToken json, string accountName, string thumbnailSuffix) - { - m_Owner = App.PolyAssetCatalog; - HumanName = json["displayName"].ToString(); - AssetId = json["name"].ToString().Substring(7); // strip out "assets/" - AccountName = accountName; - var rotation = json["presentationParams"]?["orientingRotation"]; - if (rotation != null) - { - ModelRotation = new Quaternion( - rotation["x"]?.Value() ?? 0, - rotation["y"]?.Value() ?? 0, - rotation["z"]?.Value() ?? 0, - rotation["w"]?.Value() ?? 0 - ); - } - else - { - ModelRotation = null; - } - - m_Thumbnail = new Texture2D(4, 4, TextureFormat.ARGB32, false); - m_ThumbnailUrl = json["thumbnail"]["url"].ToString(); - if (!string.IsNullOrEmpty(thumbnailSuffix)) - { - m_ThumbnailUrl = string.Format("{0}={1}", m_ThumbnailUrl, thumbnailSuffix); - } - if (!kLazyLoadThumbnail) - { - // Pre-emptive thumbnail fetch - _ = Thumbnail; - } - } - - /// Returns the contents of path, or null if the cache doesn't exist / can't be read. - /// It's ok to pass null. - /// Does not raise exceptions. - private static byte[] SafeReadCache(string path) - { - if (path != null && File.Exists(path)) - { - try - { - return File.ReadAllBytes(path); - } - catch (IOException e) - { - Debug.LogWarning($"Could not read cache {path}: {e}"); - } - } - return null; - } - - /// Updates the contents of path. - /// It's ok to pass null path or contents; passing contents=null clears the cache file. - /// Does not raise exceptions. - private static void SafeWriteCache(string path, byte[] contents) - { - if (path == null) { return; } - try { File.Delete(path); } - catch { } - if (contents != null) - { - string dir = Path.GetDirectoryName(path); - if (!Directory.Exists(dir)) - { - try { Directory.CreateDirectory(dir); } - catch { } - } - try { File.WriteAllBytes(path, contents); } - catch { } - } - } - - async void DownloadThumbnailAsync(string thumbnailUrl) - { - string cachePath = Path.Combine(m_Owner.m_ThumbnailCacheDir, AssetId); - byte[] thumbnailBytes = SafeReadCache(cachePath); - - if (thumbnailBytes == null) - { - await m_Owner.m_thumbnailFetchLimiter.WaitAsync(); - WebRequest www = new WebRequest(thumbnailUrl, - App.GoogleIdentity, - UnityWebRequest.kHttpVerbGET); - - await www.SendAsync(); - - while (m_Owner.m_thumbnailReadLimiter.IsBlocked()) - { - await Awaiters.NextFrame; - } - thumbnailBytes = www.ResultBytes; - SafeWriteCache(cachePath, thumbnailBytes); - } - - if (thumbnailBytes != null) - { - try - { - // TODO: fix aspect ratio of thumbnail - RawImage imageData = await new ThreadedImageReader(thumbnailBytes, thumbnailUrl); - - UnityEngine.Profiling.Profiler.BeginSample("AssetDetails.DownloadThumbnail:LoadImage"); - if (imageData != null) - { - m_Thumbnail.Resize(imageData.ColorWidth, imageData.ColorHeight, - TextureFormat.ARGB32, false); - m_Thumbnail.SetPixels32(imageData.ColorData); - m_Thumbnail.Apply(updateMipmaps: false, makeNoLongerReadable: true); - } - UnityEngine.Profiling.Profiler.EndSample(); - - // m_Thumbnail still points to the same Texture2D, so we don't need to send CatalogChanged - } - catch (Exception) - { - SafeWriteCache(cachePath, null); - throw; - } - } - } - } - - private static Vector3? GetCameraForward(JToken cameraParams) - { - if (cameraParams == null) - { - return null; - } - JToken cameraMatrix = cameraParams["matrix4x4"]; - if (cameraMatrix == null) { return null; } - // The third column holds the camera's forward. - Vector3 cameraForward = new Vector3(); - cameraForward.x = float.Parse(cameraMatrix[2].ToString()); - cameraForward.y = float.Parse(cameraMatrix[6].ToString()); - cameraForward.z = float.Parse(cameraMatrix[10].ToString()); - return cameraForward; - } - - private class AssetSet - { - public List m_Models = new List(); - public IEnumerator m_FetchMetadataCoroutine; - public bool m_RefreshRequested; - public float m_CooldownTimer; - } - - /// A request to pull a Model into memory. - /// It's assumed that the Model already exists on disk. - public class ModelLoadRequest - { - public readonly Model Model; - /// The reason for the Model being pulled into memory. - public readonly string Reason; - public string AssetId => Model.AssetId; - public ModelLoadRequest(Model model, string reason) - { - Model = model; - Reason = reason; - } - } - - public event Action CatalogChanged; - - [SerializeField] private string m_ThumbnailSuffix = "s128"; - /// Assets being downloaded to disk. - /// When done, these get moved to m_RequestLoadQueue. - private List m_ActiveRequests; - /// Assets that someone wants to bring from disk into memory. - /// Precondition: they are on disk - /// These get moved onto m_LoadQueue periodically. - /// May contain duplicates? - /// TODO: figure out why we have this intermediate stage - private List m_RequestLoadQueue; - private List m_LoadQueue; - /// Memoization data for IsLoading(). - /// Set this to null to invalidate it; or (if you are very confident) mutate it. - /// Invariant: either null, or the union of m_ActiveRequests, m_RequestLoadQueue, m_LoadQueue. - private HashSet m_IsLoadingMemo = null; - private string m_CacheDir; - private string m_ThumbnailCacheDir; - private Dictionary m_ModelsByAssetId; - private Dictionary m_AssetSetByType; - private bool m_NotifyListeners; - - private AwaitableRateLimiter m_thumbnailFetchLimiter = - new AwaitableRateLimiter(kThumbnailFetchRate, kThumbnailFetchMaxCount); - private RateLimiter m_thumbnailReadLimiter = - new RateLimiter(maxEventsPerFrame: kThumbnailReadRate); - - /// Returns true if the assetId is in any of our download or load queues - public bool IsLoading(string assetId) - { - // This needs caching because it's hammered every frame by the model buttons :-/ - if (m_IsLoadingMemo == null) - { - m_IsLoadingMemo = new HashSet(); - m_IsLoadingMemo.UnionWith(m_ActiveRequests.Select(request => request.Asset.Id)); - m_IsLoadingMemo.UnionWith(m_RequestLoadQueue.Select(request => request.AssetId)); - m_IsLoadingMemo.UnionWith(m_LoadQueue.Select(request => request.AssetId)); - } - return m_IsLoadingMemo.Contains(assetId); - } - - public void RequestRefresh(PolySetType type) - { - // We don't update featured except on startup. - if (type != PolySetType.Featured && App.GoogleIdentity.LoggedIn) - { - m_AssetSetByType[type].m_RefreshRequested = true; - } - } - - public void Init() - { - string cacheDir = Path.Combine(Application.persistentDataPath, "assetCache"); - m_CacheDir = cacheDir.Replace("\\", "/"); - // Use a different directory from m_CacheDir to avoid having to make ValidGltfCache() - // smart enough to allow directories with only a thumbnail and no asset data. - m_ThumbnailCacheDir = Path.Combine(Application.persistentDataPath, "assetThumbnail") - .Replace("\\", "/"); - m_ActiveRequests = new List(); - m_RequestLoadQueue = new List(); - m_LoadQueue = new List(); - - FileUtils.InitializeDirectoryWithUserError(m_CacheDir, "Failed to create asset cache"); - - // Create and populate model map. - m_ModelsByAssetId = new Dictionary(); - try - { - foreach (string folderPath in EnumerateCacheDirectories()) - { - string folderName = Path.GetFileName(folderPath); - string gltfFile = ValidGltfCache(folderPath, folderName); - if (gltfFile != null) - { - string path = Path.Combine(folderPath, folderName); - path = Path.Combine(path, gltfFile); - m_ModelsByAssetId[folderName] = new Model(Model.Location.PolyAsset(folderName, path)); - } - else - { - Debug.LogWarningFormat("Deleting invalid cache folder {0}", folderName); - Directory.Delete(folderPath, true); - } - } - } - catch (DirectoryNotFoundException e) - { - Debug.LogException(e); - } - catch (UnauthorizedAccessException e) - { - Debug.LogException(e); - } - - m_AssetSetByType = new Dictionary - { - { - PolySetType.User, - new AssetSet() - }, - { - PolySetType.Liked, - new AssetSet() - }, - { - PolySetType.Featured, - new AssetSet { m_RefreshRequested = true } - } - }; - - App.Instance.AppExit += () => - { - var models = EnumerateCacheDirectories() - .OrderBy(d => Directory.GetLastAccessTimeUtc(d)).ToArray(); - for (int excess = models.Count() - kAssetDiskCacheSize; excess > 0; excess--) - { - Directory.Delete(models[excess - 1], true); - } - }; - } - - public AssetLoadState GetAssetLoadState(string assetId) - { - if (GetModel(assetId) is Model m) - { - // A model may be present in memory but also be still loading -- eg if someone - // requested that the load be retried. In this case it's kind of in two states; - // I'm somewhat arbitrarily choosing one. - if (m.m_Valid) { return AssetLoadState.Loaded; } - else if (m.Error != null) { return AssetLoadState.LoadFailed; } - else if (IsLoading(assetId)) - { - foreach (var elt in m_RequestLoadQueue) - { - if (elt.AssetId == assetId) - { - return AssetLoadState.Loading; - } - } - foreach (var elt in m_LoadQueue) - { - if (elt.AssetId == assetId) - { - return AssetLoadState.Loading; - } - } - // This should never happen and probably indicates some bug where m_AssetLoading hasn't - // been kept in sync with m_[Request]LoadQueue. - Debug.LogWarning($"Model for {assetId} is in an indeterminate state!"); - return AssetLoadState.Unknown; - } - else - { - return AssetLoadState.Downloaded; - } - } - else - { - foreach (var downloadRequest in m_ActiveRequests) - { - if (downloadRequest.Asset.Id == assetId) - { - return AssetLoadState.Downloading; - } - } - return AssetLoadState.NotDownloaded; - } - } - - public string GetCacheDirectoryForAsset(string asset) - { - if (!sm_AssetIdPattern.IsMatch(asset)) - { - Debug.LogWarningFormat("Not an asset id: {0}", asset); - return null; - } - return Path.Combine(m_CacheDir, asset); - } - - /// On any error, returns an empty enumeration - public IEnumerable EnumerateCacheDirectories() - { - try - { - return Directory.GetDirectories(m_CacheDir); - } - catch (UnauthorizedAccessException e) { Debug.LogException(e); } - catch (DirectoryNotFoundException e) { Debug.LogException(e); } - return new string[] { }; - } - - void Start() - { - OAuth2Identity.ProfileUpdated += OnProfileUpdated; - RefreshFetchCoroutines(); - } - - public Model GetModel(string assetId) - { - Model model; - if (!m_ModelsByAssetId.TryGetValue(assetId, out model)) - { - // null is actually the default for reference types, just being explicit here. - // ReSharper disable once RedundantAssignment - model = null; - } - return model; - } - - /// Checks to see if it's time to kick off a new refresh - /// Polls any refresh coroutines going on. - void Update() - { - m_thumbnailFetchLimiter.Tick(Time.deltaTime); - if (!VrAssetService.m_Instance.Available) - { - return; - } - - foreach (var entry in m_AssetSetByType) - { - var type = entry.Key; - var set = entry.Value; - - if (set.m_FetchMetadataCoroutine != null) - { - // Pump existing update coroutine - try - { - if (!set.m_FetchMetadataCoroutine.MoveNext()) - { - set.m_FetchMetadataCoroutine = null; - } - } - catch (VrAssetServiceException e) - { - ControllerConsoleScript.m_Instance.AddNewLine(e.Message); - Debug.LogException(e); - set.m_FetchMetadataCoroutine = null; - } - } - else if (set.m_RefreshRequested) - { - // Kick off a new refresh coroutine if it is time. - if (set.m_CooldownTimer <= 0) - { - set.m_FetchMetadataCoroutine = RefreshAssetSet(type); - set.m_RefreshRequested = false; - set.m_CooldownTimer = VrAssetService.m_Instance.m_SketchbookRefreshInterval; - } - } - if (set.m_CooldownTimer >= 0) - { - set.m_CooldownTimer -= Time.deltaTime; - } - } - } - - /// Pass the reason the Model is being pulled into memory, for logging purposes. - public void RequestModelLoad(Model model, string reason) - { - // Verify assumption that byAssetId[model.asset] == model; otherwise, caller may wait - // indefinitely for model's loaded state to change and that bug will be hard to track down. - string assetId = model.GetLocation().AssetId; - m_ModelsByAssetId.TryGetValue(assetId, out Model model2); - if (model2 != model) - { - // If we pretend to try to load the model, the caller may wait infinitely for the Model - // to load. - throw new InvalidOperationException($"Duplicate {assetId}"); - } - RequestModelLoad(assetId, reason); - } - - /// Request loading a model with a given Poly Asset ID. - /// Pass the reason the Model is being pulled into memory, for logging purposes. - /// - /// Upon completion, the asset will: - /// - be in "failed download" state (don't know how to check for this) - /// - be in "download succeeded, load failed" state (check Model.Error != null) - /// - be in "download succeeded, load succeeded" state (check Model.m_Valid) - /// - /// The intent is that this method will ignore previous failures and try again. - /// If you don't want to retry a failed load-into-memory, you should check Model.Error first. - /// If you aren't trying to do a hot-reload, you should check Model.m_Valid first. - public void RequestModelLoad(string assetId, string reason) - { - // Don't attempt to load models which are already loading. - if (IsLoading(assetId)) - { - return; - } - - if (m_ModelsByAssetId.ContainsKey(assetId)) - { - // Already downloaded. - // It may be in memory already, but it's safe to ask for it to be brought in again. - // That way we get the behavior of "ignore a failed load-into-memory" - m_RequestLoadQueue.Add(new ModelLoadRequest(m_ModelsByAssetId[assetId], reason)); - m_IsLoadingMemo.Add(assetId); - } - else - { - // Not downloaded yet. - // Kick off a download; when done the load will and arrange for the download-complete to kick off the - // load-into-memory work. - string assetDir = GetCacheDirectoryForAsset(assetId); - try - { - // For the case that the folder exists, but the files were removed. - if (!Directory.Exists(assetDir)) - { - Directory.CreateDirectory(assetDir); - } - } - catch (UnauthorizedAccessException) - { - Debug.LogError("Cannot create directory for online asset download."); - } - - // Then request the asset from Poly. - AssetGetter request = VrAssetService.m_Instance.GetAsset( - assetId, VrAssetFormat.GLTF2, reason); - StartCoroutine(request.GetAssetCoroutine()); - m_ActiveRequests.Add(request); - m_IsLoadingMemo.Add(assetId); - } - } - - /// The inverse of RequestModelLoad(). - /// Returns true if the model is no longer in any load queues. - /// The current implementation is only a half-hearted effort, so it may return false. - public bool CancelRequestModelLoad(string assetId) - { - if (IsLoading(assetId)) - { - // Might be tricky to safely remove from this queue, but at least mark it so that - // it doesn't go from "downloading" to "loading into memory" - bool isInActiveRequests = false; - foreach (var elt in m_ActiveRequests) - { - if (elt.Asset.Id == assetId) - { - elt.IsCanceled = true; - isInActiveRequests = true; - } - } - - // Removing from RequestLoadQueue is easy; there's no computation associated with it (yet) - m_RequestLoadQueue.RemoveAll(elt => elt.AssetId == assetId); - bool isInRequestLoadQueue = false; - - { - bool wasInLoadQueue = false; - foreach (var elt in m_LoadQueue) - { - if (elt.AssetId == assetId) - { - elt.Model.CancelLoadModelAsync(); - wasInLoadQueue = true; - } - } - if (wasInLoadQueue) - { - m_LoadQueue = m_LoadQueue.Where(elt => elt.AssetId != assetId).ToList(); - } - } - bool isInLoadQueue = false; - - // Could just invalidate the cache, but we're going to have to rebuild it in just a moment, - // and we have enough information to mutate it properly. - if (!isInActiveRequests && !isInRequestLoadQueue && !isInLoadQueue) - { - m_IsLoadingMemo.Remove(assetId); - } - } - - return !IsLoading(assetId); - } - - /// Downloads models referenced by the passed sketch. - /// Pass the reason this is happening. - /// TODO: maybe annotate the download request so we can choose whether they turn - /// into model loads? - public void PrecacheModels(SceneFileInfo sceneFileInfo, string reason) - { - if (string.IsNullOrEmpty(App.Config.GoogleSecrets?.ApiKey)) - { - return; - } - StartCoroutine(PrecacheModelsCoroutine(sceneFileInfo, reason)); - } - - /// Waits for the json data to be read on a background thread, and then executes a precache - /// coroutine for each found asset. - private IEnumerator PrecacheModelsCoroutine(SceneFileInfo sceneFileInfo, string reason) - { - var getIdsFuture = new Future>(() => GetModelIds(sceneFileInfo)); - List ids; - while (true) - { - try - { - if (getIdsFuture.TryGetResult(out ids)) { break; } - } - catch (FutureFailed e) - { - throw new Exception($"While reading {sceneFileInfo}", e); - } - yield return null; - } - - if (ids == null) { yield break; } - List> precacheCoroutines = new List>(); - // Only trigger off one precache routine per frame. - foreach (string id in ids) - { - if (m_ModelsByAssetId.ContainsKey(id)) - { - // Already cached - continue; - } - if (!FileUtils.InitializeDirectory(GetCacheDirectoryForAsset(id))) - { - continue; - } - precacheCoroutines.Add(PrecacheCoroutine( - VrAssetService.m_Instance.GetAsset(id, VrAssetFormat.GLTF2, reason))); - yield return null; - } - - var cr = CoroutineUtil.CompleteAllCoroutines(precacheCoroutines); - while (cr.MoveNext()) - { - yield return cr.Current; - } - } - - /// Returns all non-null asset ids from the passed sketch's metadata. - /// null return value means "empty list". - /// Raises exception on error. - private static List GetModelIds(SceneFileInfo sceneFileInfo) - { - // Json deserializing is in a separate method that doesn't access Unity objects so that it - // can be called on a thread. The json deserializing can be pretty slow and can cause - // frame drops if performed on the main thread. - Stream metadata = SaveLoadScript.GetMetadataReadStream(sceneFileInfo); - if (metadata == null) - { - if (sceneFileInfo.Exists) - { - // ??? Let's try to provoke an exception to propagate to the caller - using (var dummy = File.OpenRead(sceneFileInfo.FullPath)) { } - throw new Exception($"Unknown error opening metadata {sceneFileInfo.FullPath}"); - } - else - { - throw new Exception( - "Reading metadata from nonexistent " + - $"{sceneFileInfo.InfoType} {sceneFileInfo.HumanName}"); - } - } - using (var jsonReader = new JsonTextReader(new StreamReader(metadata))) - { - var jsonData = SaveLoadScript.m_Instance.DeserializeMetadata(jsonReader); - if (SaveLoadScript.m_Instance.LastMetadataError != null) - { - throw new Exception($"Deserialize error: {SaveLoadScript.m_Instance.LastMetadataError}"); - } - if (jsonData.ModelIndex == null) { return null; } - return jsonData.ModelIndex.Select(m => m.AssetId).Where(a => a != null).ToList(); - } - } - - // The directory for the asset must have already been created - IEnumerator PrecacheCoroutine(AssetGetter request) - { - string assetId = request.Asset.Id; - var cr = request.GetAssetCoroutine(); - while (true) - { - try - { - bool result = cr.MoveNext(); - if (!result) - { - break; - } - } - catch (VrAssetServiceException e) - { - ControllerConsoleScript.m_Instance.AddNewLine(e.Message); - Debug.LogException(e); - yield break; - } - yield return cr.Current; - } - while (!request.IsReady) { yield return null; } - request.Asset.WriteToDisk(); - string path = Path.Combine(GetCacheDirectoryForAsset(assetId), request.Asset.RootFilePath); - m_ModelsByAssetId[assetId] = new Model(Model.Location.PolyAsset(assetId, path)); - } - - public void UpdateCatalog() - { - // Walk backwards so removal doesn't mess up our indexing. - for (int i = m_ActiveRequests.Count - 1; i >= 0; --i) - { - AssetGetter request = m_ActiveRequests[i]; - if (request.IsReady || request.IsCanceled) - { - if (request.Asset.ValidAsset) - { - if (request.Asset.WriteToDisk()) - { - string assetId = request.Asset.Id; - string path = - Path.Combine(GetCacheDirectoryForAsset(assetId), request.Asset.RootFilePath); - // TODO: This assumes PolyRawAssets are models. This may not be true in the - // future and should the VrAssetProtos.ElementType request parameter to - // VrAssetService.m_Instance.GetAsset to decide how to store and index the asset. - - // Populate map entry for this new model. - m_ModelsByAssetId[assetId] = new Model(Model.Location.PolyAsset(assetId, path)); - - // After download the model should be loaded too, unless the request was canceled. - // TODO: this seems a littttle suspect. Just because it finished downloading, - // does that mean we still want to bring it into memory? - if (!request.IsCanceled) - { - m_RequestLoadQueue.Add( - new ModelLoadRequest( - m_ModelsByAssetId[assetId], $"{request.Reason} fetched")); - } - else - { - // Just reset, in case asset is on one of the other queues. - m_IsLoadingMemo = null; - } - } - } - else - { - Debug.LogWarning("Downloaded asset is empty " + request.Asset.RootFilePath); - } - - m_ActiveRequests.RemoveAt(i); - m_NotifyListeners = true; - } - } - - if (m_RequestLoadQueue.Count > 0 && m_LoadQueue.Count == 0) - { - // Move a single item from "request load" to "load". Too many items on the load queue - // causes bad stuttering (at least for heavy models). - var toMove = m_RequestLoadQueue[0]; - // TODO: how is it possible for m_RequestLoadQueue to contain duplicates? - m_RequestLoadQueue = m_RequestLoadQueue - .Where(elt => elt.AssetId != toMove.AssetId) - .ToList(); - m_LoadQueue.Add(toMove); - } - - // Always call this to poll the async loader. - LoadModelsInQueueAsync(); - - // Shout from the hills. - if (m_NotifyListeners) - { - if (CatalogChanged != null) - { - CatalogChanged(); - } - m_NotifyListeners = false; - } - } - - void LoadModelsInQueueAsync() - { - UnityEngine.Profiling.Profiler.BeginSample("PAC.LoadModelsInQueueAsync"); - for (int i = m_LoadQueue.Count - 1; i >= 0; --i) - { - Model model = m_LoadQueue[i].Model; - if (!model.IsLoading()) - { - // If the overlay is up, hitching is okay; so avoid the slow threaded image load. - bool useThreadedImageLoad = - OverlayManager.m_Instance.CurrentOverlayState == OverlayState.Hidden; - model.LoadModelAsync(useThreadedImageLoad); - } - else - { - if (model.TryLoadModel()) - { - m_LoadQueue.RemoveAt(i); - m_IsLoadingMemo = null; - m_NotifyListeners = true; - } - } - } - UnityEngine.Profiling.Profiler.EndSample(); - } - - private static HashSet SetMinus(HashSet lhs, HashSet rhs) - { - var result = new HashSet(lhs); - result.ExceptWith(rhs); - return result; - } - - private IEnumerator RefreshAssetSet(PolySetType type) - { - List models = new List(); - // When the list is empty, make it the actual list acted upon so that results start - // showing up immediately. - if (m_AssetSetByType[type].m_Models.Count == 0) - { - m_AssetSetByType[type].m_Models = models; - } - AssetLister lister = VrAssetService.m_Instance.ListAssets(type); - while (lister.HasMore || models.Count == 0) - { - using (var cr = lister.NextPage(models, m_ThumbnailSuffix)) - { - while (true) - { - try - { - if (!cr.MoveNext()) - { - break; - } - } - catch (VrAssetServiceException e) - { - ControllerConsoleScript.m_Instance.AddNewLine(e.Message); - Debug.LogException(e); - yield break; - } - yield return cr.Current; - } - } - if (models.Count == 0) - { - break; - } - } - // As the assets may already have models loaded into them, just add any new models and - // remove old ones. - var newIds = new HashSet(models.Select(m => m.AssetId)); - var oldIds = new HashSet(m_AssetSetByType[type].m_Models.Select(m => m.AssetId)); - // These must be reified; if they are left as lazy IEnumerables, O(n^2) behavior results - HashSet toAdd = SetMinus(newIds, oldIds); - HashSet toRemove = SetMinus(oldIds, newIds); - m_AssetSetByType[type].m_Models.RemoveAll(m => toRemove.Contains(m.AssetId)); - m_AssetSetByType[type].m_Models.InsertRange(0, models.Where(m => toAdd.Contains(m.AssetId))); - if (CatalogChanged != null) - { - CatalogChanged(); - } - } - - void RefreshFetchCoroutines() - { - if (App.GoogleIdentity.Profile != null) - { - m_AssetSetByType[PolySetType.User].m_RefreshRequested = true; - m_AssetSetByType[PolySetType.Liked].m_RefreshRequested = true; - } - else - { - AssetSet set = m_AssetSetByType[PolySetType.User]; - if (set.m_FetchMetadataCoroutine != null) - { - StopCoroutine(set.m_FetchMetadataCoroutine); - set.m_FetchMetadataCoroutine = null; - } - set.m_Models.Clear(); - set = m_AssetSetByType[PolySetType.Liked]; - if (set.m_FetchMetadataCoroutine != null) - { - StopCoroutine(set.m_FetchMetadataCoroutine); - set.m_FetchMetadataCoroutine = null; - } - set.m_Models.Clear(); - if (CatalogChanged != null) - { - CatalogChanged(); - } - } - } - - void OnProfileUpdated(OAuth2Identity _) - { - RefreshFetchCoroutines(); - } - - void OnDestroy() - { - OAuth2Identity.ProfileUpdated -= OnProfileUpdated; - } - - public int NumCloudModels(PolySetType type) - { - return m_AssetSetByType[type].m_Models.Count(); - } - - public AssetDetails GetPolyAsset(PolySetType type, int index) - { - return m_AssetSetByType[type].m_Models[index]; - } - - // Ideally we would check against the format info from Poly that we have all the required - // elements but for now we know that there should be exactly one .gltf/.gltf2 and a .bin - // Returns the filename of the .gltf/.gltf2 file, or null if not valid. - private static string ValidGltfCache(string dir, string assetId) - { - if (Directory.GetFiles(dir, "*.bin").Length == 0) - { - return null; - } - - var filesGltf1 = Directory.GetFiles(dir, "*.gltf"); - var filesGltf2 = Directory.GetFiles(dir, "*.gltf2"); - if (filesGltf1.Length + filesGltf2.Length != 1) - { - return null; - } - else if (filesGltf1.Length == 1) - { - return filesGltf1[0]; - } - else - { - return filesGltf2[0]; - } - } - - public void ClearLoadingQueue() - { - m_LoadQueue.Clear(); - m_RequestLoadQueue.Clear(); - m_IsLoadingMemo = null; - foreach (var req in m_ActiveRequests) - { - req.IsCanceled = true; - } - } - - public void UnloadUnusedModels() - { - foreach (var model in m_ModelsByAssetId.Values.Where(x => x != null && x.m_UsageCount == 0)) - { - model.UnloadModel(); - } - } - } - -} // namespace TiltBrush +// Copyright 2020 The Tilt Brush Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// 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 System; +using System.Linq; +using System.Collections.Generic; +using System.IO; +using System.Text.RegularExpressions; +using Newtonsoft.Json.Linq; +using Newtonsoft.Json; + +namespace TiltBrush +{ + + /// Used as an accessor for files downloaded from Poly and cached on local storage. + public partial class IcosaAssetCatalog : MonoBehaviour + { + const int kAssetDiskCacheSize = 1000; + const float kThumbnailFetchRate = 15; + const int kThumbnailFetchMaxCount = 30; + const int kThumbnailReadRate = 4; + + // This may be a bit broader than an asset id, but it's a safe set of + // filename characters. + // Change - added . % ~ to allow urlencoded urls + static readonly Regex sm_AssetIdPattern = new Regex(@"^[a-zA-Z0-9-_%~\.]+$"); + + public enum AssetLoadState + { + Unknown, + NotDownloaded, + Downloading, + Downloaded, // On disk but not in memory + // DownloadFailed, // We don't keep track of download errors, so this becomes "NotDownloaded" + Loading, + LoadFailed, // This shows up as a !Valid model in the model catalog + Loaded + } + + public class AssetDetails + { + // Disabled only because there isn't a pressing reason to enable it. + const bool kLazyLoadThumbnail = false; + + private readonly IcosaAssetCatalog m_Owner; + private readonly Texture2D m_Thumbnail; + private string m_ThumbnailUrl; // if non-null, have not attempted to fetch it yet + + public string AssetId { get; } + public string HumanName { get; } + public string AccountName { get; } + public Quaternion? ModelRotation { get; } + + public Texture2D Thumbnail + { + get + { + if (m_ThumbnailUrl != null) + { + string url = m_ThumbnailUrl; + m_ThumbnailUrl = null; + DownloadThumbnailAsync(url); + } + return m_Thumbnail; + } + } + + public Model Model { get { return App.IcosaAssetCatalog.GetModel(AssetId); } } + + public AssetDetails( + JToken json, string accountName, string thumbnailSuffix) + { + m_Owner = App.IcosaAssetCatalog; + HumanName = json["displayName"].ToString(); + AssetId = json["assetId"].ToString(); + AccountName = accountName; + var rotation = json["presentationParams"]?["orientingRotation"]; + if (rotation != null) + { + ModelRotation = new Quaternion( + rotation["x"]?.Value() ?? 0, + rotation["y"]?.Value() ?? 0, + rotation["z"]?.Value() ?? 0, + rotation["w"]?.Value() ?? 0 + ); + } + else + { + ModelRotation = null; + } + + m_Thumbnail = new Texture2D(4, 4, TextureFormat.ARGB32, false); + m_ThumbnailUrl = json?["thumbnail"]?["url"]?.ToString(); + if (!string.IsNullOrEmpty(thumbnailSuffix)) + { + m_ThumbnailUrl = string.Format("{0}={1}", m_ThumbnailUrl, thumbnailSuffix); + } + if (!kLazyLoadThumbnail) + { + // Pre-emptive thumbnail fetch + _ = Thumbnail; + } + } + + /// Returns the contents of path, or null if the cache doesn't exist / can't be read. + /// It's ok to pass null. + /// Does not raise exceptions. + private static byte[] SafeReadCache(string path) + { + if (path != null && File.Exists(path)) + { + try + { + return File.ReadAllBytes(path); + } + catch (IOException e) + { + Debug.LogWarning($"Could not read cache {path}: {e}"); + } + } + return null; + } + + /// Updates the contents of path. + /// It's ok to pass null path or contents; passing contents=null clears the cache file. + /// Does not raise exceptions. + private static void SafeWriteCache(string path, byte[] contents) + { + if (path == null) { return; } + try { File.Delete(path); } + catch { } + if (contents != null) + { + string dir = Path.GetDirectoryName(path); + if (!Directory.Exists(dir)) + { + try { Directory.CreateDirectory(dir); } + catch { } + } + try { File.WriteAllBytes(path, contents); } + catch { } + } + } + + async void DownloadThumbnailAsync(string thumbnailUrl) + { + string cachePath = Path.Combine(m_Owner.m_ThumbnailCacheDir, AssetId); + byte[] thumbnailBytes = SafeReadCache(cachePath); + + if (thumbnailBytes == null) + { + await m_Owner.m_thumbnailFetchLimiter.WaitAsync(); + WebRequest www = new WebRequest(thumbnailUrl); + await www.SendAsync(); + + while (m_Owner.m_thumbnailReadLimiter.IsBlocked()) + { + await Awaiters.NextFrame; + } + thumbnailBytes = www.ResultBytes; + SafeWriteCache(cachePath, thumbnailBytes); + } + + if (thumbnailBytes != null) + { + try + { + // TODO: fix aspect ratio of thumbnail + RawImage imageData = await new ThreadedImageReader(thumbnailBytes, thumbnailUrl); + + UnityEngine.Profiling.Profiler.BeginSample("AssetDetails.DownloadThumbnail:LoadImage"); + if (imageData != null) + { + m_Thumbnail.Resize(imageData.ColorWidth, imageData.ColorHeight, + TextureFormat.ARGB32, false); + m_Thumbnail.SetPixels32(imageData.ColorData); + m_Thumbnail.Apply(updateMipmaps: false, makeNoLongerReadable: true); + } + UnityEngine.Profiling.Profiler.EndSample(); + + // m_Thumbnail still points to the same Texture2D, so we don't need to send CatalogChanged + } + catch (Exception) + { + SafeWriteCache(cachePath, null); + throw; + } + } + } + } + + private static Vector3? GetCameraForward(JToken cameraParams) + { + if (cameraParams == null) + { + return null; + } + JToken cameraMatrix = cameraParams["matrix4x4"]; + if (cameraMatrix == null) { return null; } + // The third column holds the camera's forward. + Vector3 cameraForward = new Vector3(); + cameraForward.x = float.Parse(cameraMatrix[2].ToString()); + cameraForward.y = float.Parse(cameraMatrix[6].ToString()); + cameraForward.z = float.Parse(cameraMatrix[10].ToString()); + return cameraForward; + } + + private class AssetSet + { + public List m_Models = new List(); + public IEnumerator m_FetchMetadataCoroutine; + public bool m_RefreshRequested; + public float m_CooldownTimer; + } + + /// A request to pull a Model into memory. + /// It's assumed that the Model already exists on disk. + public class ModelLoadRequest + { + public readonly Model Model; + /// The reason for the Model being pulled into memory. + public readonly string Reason; + public string AssetId => Model.AssetId; + public ModelLoadRequest(Model model, string reason) + { + Model = model; + Reason = reason; + } + } + + public event Action CatalogChanged; + + [SerializeField] private string m_ThumbnailSuffix = "s128"; + /// Assets being downloaded to disk. + /// When done, these get moved to m_RequestLoadQueue. + private List m_ActiveRequests; + /// Assets that someone wants to bring from disk into memory. + /// Precondition: they are on disk + /// These get moved onto m_LoadQueue periodically. + /// May contain duplicates? + /// TODO: figure out why we have this intermediate stage + private List m_RequestLoadQueue; + private List m_LoadQueue; + /// Memoization data for IsLoading(). + /// Set this to null to invalidate it; or (if you are very confident) mutate it. + /// Invariant: either null, or the union of m_ActiveRequests, m_RequestLoadQueue, m_LoadQueue. + private HashSet m_IsLoadingMemo = null; + private string m_CacheDir; + private string m_ThumbnailCacheDir; + private Dictionary m_ModelsByAssetId; + private Dictionary m_AssetSetByType; + private bool m_NotifyListeners; + + private AwaitableRateLimiter m_thumbnailFetchLimiter = + new AwaitableRateLimiter(kThumbnailFetchRate, kThumbnailFetchMaxCount); + private RateLimiter m_thumbnailReadLimiter = + new RateLimiter(maxEventsPerFrame: kThumbnailReadRate); + + /// Returns true if the assetId is in any of our download or load queues + public bool IsLoading(string assetId) + { + // This needs caching because it's hammered every frame by the model buttons :-/ + if (m_IsLoadingMemo == null) + { + m_IsLoadingMemo = new HashSet(); + m_IsLoadingMemo.UnionWith(m_ActiveRequests.Select(request => request.Asset.Id)); + m_IsLoadingMemo.UnionWith(m_RequestLoadQueue.Select(request => request.AssetId)); + m_IsLoadingMemo.UnionWith(m_LoadQueue.Select(request => request.AssetId)); + } + return m_IsLoadingMemo.Contains(assetId); + } + + public void RequestRefresh(IcosaSetType type) + { + // We don't update featured except on startup + if (type != IcosaSetType.Featured && App.IcosaIsLoggedIn) + { + m_AssetSetByType[type].m_RefreshRequested = true; + } + } + + public void Init() + { + string cacheDir = Path.Combine(Application.persistentDataPath, "assetCache"); + m_CacheDir = cacheDir.Replace("\\", "/"); + // Use a different directory from m_CacheDir to avoid having to make ValidGltfCache() + // smart enough to allow directories with only a thumbnail and no asset data. + m_ThumbnailCacheDir = Path.Combine(Application.persistentDataPath, "assetThumbnail") + .Replace("\\", "/"); + m_ActiveRequests = new List(); + m_RequestLoadQueue = new List(); + m_LoadQueue = new List(); + + FileUtils.InitializeDirectoryWithUserError(m_CacheDir, "Failed to create asset cache"); + + // Create and populate model map. + m_ModelsByAssetId = new Dictionary(); + try + { + foreach (string folderPath in EnumerateCacheDirectories()) + { + string folderName = Path.GetFileName(folderPath); + string gltfFile = ValidGltfCache(folderPath, folderName); + if (gltfFile != null) + { + string path = Path.Combine(folderPath, folderName); + path = Path.Combine(path, gltfFile); + m_ModelsByAssetId[folderName] = new Model(Model.Location.IcosaAsset(folderName, path)); + } + else + { + Debug.LogWarningFormat("Deleting invalid cache folder {0}", folderName); + Directory.Delete(folderPath, true); + } + } + } + catch (DirectoryNotFoundException e) + { + Debug.LogException(e); + } + catch (UnauthorizedAccessException e) + { + Debug.LogException(e); + } + + m_AssetSetByType = new Dictionary + { + { + IcosaSetType.User, + new AssetSet() + }, + { + IcosaSetType.Liked, + new AssetSet() + }, + { + IcosaSetType.Featured, + new AssetSet { m_RefreshRequested = true } + } + }; + + App.Instance.AppExit += () => + { + var models = EnumerateCacheDirectories() + .OrderBy(d => Directory.GetLastAccessTimeUtc(d)).ToArray(); + for (int excess = models.Count() - kAssetDiskCacheSize; excess > 0; excess--) + { + Directory.Delete(models[excess - 1], true); + } + }; + } + + public AssetLoadState GetAssetLoadState(string assetId) + { + if (GetModel(assetId) is Model m) + { + // A model may be present in memory but also be still loading -- eg if someone + // requested that the load be retried. In this case it's kind of in two states; + // I'm somewhat arbitrarily choosing one. + if (m.m_Valid) { return AssetLoadState.Loaded; } + else if (m.Error != null) { return AssetLoadState.LoadFailed; } + else if (IsLoading(assetId)) + { + foreach (var elt in m_RequestLoadQueue) + { + if (elt.AssetId == assetId) + { + return AssetLoadState.Loading; + } + } + foreach (var elt in m_LoadQueue) + { + if (elt.AssetId == assetId) + { + return AssetLoadState.Loading; + } + } + // This should never happen and probably indicates some bug where m_AssetLoading hasn't + // been kept in sync with m_[Request]LoadQueue. + Debug.LogWarning($"Model for {assetId} is in an indeterminate state!"); + return AssetLoadState.Unknown; + } + else + { + return AssetLoadState.Downloaded; + } + } + else + { + foreach (var downloadRequest in m_ActiveRequests) + { + if (downloadRequest.Asset.Id == assetId) + { + return AssetLoadState.Downloading; + } + } + return AssetLoadState.NotDownloaded; + } + } + + public string GetCacheDirectoryForAsset(string asset) + { + if (!sm_AssetIdPattern.IsMatch(asset)) + { + Debug.LogWarningFormat("Not an asset id: {0}", asset); + return null; + } + return Path.Combine(m_CacheDir, asset); + } + + /// On any error, returns an empty enumeration + public IEnumerable EnumerateCacheDirectories() + { + try + { + return Directory.GetDirectories(m_CacheDir); + } + catch (UnauthorizedAccessException e) { Debug.LogException(e); } + catch (DirectoryNotFoundException e) { Debug.LogException(e); } + return new string[] { }; + } + + void Start() + { + OAuth2Identity.ProfileUpdated += OnProfileUpdated; + RefreshFetchCoroutines(); + } + + public Model GetModel(string assetId) + { + Model model; + if (!m_ModelsByAssetId.TryGetValue(assetId, out model)) + { + // null is actually the default for reference types, just being explicit here. + // ReSharper disable once RedundantAssignment + model = null; + } + return model; + } + + /// Checks to see if it's time to kick off a new refresh + /// Polls any refresh coroutines going on. + void Update() + { + m_thumbnailFetchLimiter.Tick(Time.deltaTime); + if (!VrAssetService.m_Instance.Available) + { + return; + } + + foreach (var entry in m_AssetSetByType) + { + var type = entry.Key; + var set = entry.Value; + + if (set.m_FetchMetadataCoroutine != null) + { + // Pump existing update coroutine + try + { + if (!set.m_FetchMetadataCoroutine.MoveNext()) + { + set.m_FetchMetadataCoroutine = null; + } + } + catch (VrAssetServiceException e) + { + ControllerConsoleScript.m_Instance.AddNewLine(e.Message); + Debug.LogException(e); + set.m_FetchMetadataCoroutine = null; + } + } + else if (set.m_RefreshRequested) + { + // Kick off a new refresh coroutine if it is time. + if (set.m_CooldownTimer <= 0) + { + set.m_FetchMetadataCoroutine = RefreshAssetSet(type); + set.m_RefreshRequested = false; + set.m_CooldownTimer = VrAssetService.m_Instance.m_SketchbookRefreshInterval; + } + } + if (set.m_CooldownTimer >= 0) + { + set.m_CooldownTimer -= Time.deltaTime; + } + } + } + + /// Pass the reason the Model is being pulled into memory, for logging purposes. + public void RequestModelLoad(Model model, string reason) + { + // Verify assumption that byAssetId[model.asset] == model; otherwise, caller may wait + // indefinitely for model's loaded state to change and that bug will be hard to track down. + string assetId = model.GetLocation().AssetId; + m_ModelsByAssetId.TryGetValue(assetId, out Model model2); + if (model2 != model) + { + // If we pretend to try to load the model, the caller may wait infinitely for the Model + // to load. + throw new InvalidOperationException($"Duplicate {assetId}"); + } + RequestModelLoad(assetId, reason); + } + + /// Request loading a model with a given Poly Asset ID. + /// Pass the reason the Model is being pulled into memory, for logging purposes. + /// + /// Upon completion, the asset will: + /// - be in "failed download" state (don't know how to check for this) + /// - be in "download succeeded, load failed" state (check Model.Error != null) + /// - be in "download succeeded, load succeeded" state (check Model.m_Valid) + /// + /// The intent is that this method will ignore previous failures and try again. + /// If you don't want to retry a failed load-into-memory, you should check Model.Error first. + /// If you aren't trying to do a hot-reload, you should check Model.m_Valid first. + public void RequestModelLoad(string assetId, string reason) + { + // Don't attempt to load models which are already loading. + if (IsLoading(assetId)) + { + return; + } + + if (m_ModelsByAssetId.ContainsKey(assetId)) + { + // Already downloaded. + // It may be in memory already, but it's safe to ask for it to be brought in again. + // That way we get the behavior of "ignore a failed load-into-memory" + m_RequestLoadQueue.Add(new ModelLoadRequest(m_ModelsByAssetId[assetId], reason)); + m_IsLoadingMemo.Add(assetId); + } + else + { + // Not downloaded yet. + // Kick off a download; when done the load will and arrange for the download-complete to kick off the + // load-into-memory work. + string assetDir = GetCacheDirectoryForAsset(assetId); + try + { + // For the case that the folder exists, but the files were removed. + if (!Directory.Exists(assetDir)) + { + Directory.CreateDirectory(assetDir); + } + } + catch (UnauthorizedAccessException) + { + Debug.LogError("Cannot create directory for online asset download."); + } + + // Then request the asset from Poly. + AssetGetter request = VrAssetService.m_Instance.GetAsset( + assetId, VrAssetFormat.GLTF2, reason); + StartCoroutine(request.GetAssetCoroutine()); + m_ActiveRequests.Add(request); + m_IsLoadingMemo.Add(assetId); + } + } + + /// The inverse of RequestModelLoad(). + /// Returns true if the model is no longer in any load queues. + /// The current implementation is only a half-hearted effort, so it may return false. + public bool CancelRequestModelLoad(string assetId) + { + if (IsLoading(assetId)) + { + // Might be tricky to safely remove from this queue, but at least mark it so that + // it doesn't go from "downloading" to "loading into memory" + bool isInActiveRequests = false; + foreach (var elt in m_ActiveRequests) + { + if (elt.Asset.Id == assetId) + { + elt.IsCanceled = true; + isInActiveRequests = true; + } + } + + // Removing from RequestLoadQueue is easy; there's no computation associated with it (yet) + m_RequestLoadQueue.RemoveAll(elt => elt.AssetId == assetId); + bool isInRequestLoadQueue = false; + + { + bool wasInLoadQueue = false; + foreach (var elt in m_LoadQueue) + { + if (elt.AssetId == assetId) + { + elt.Model.CancelLoadModelAsync(); + wasInLoadQueue = true; + } + } + if (wasInLoadQueue) + { + m_LoadQueue = m_LoadQueue.Where(elt => elt.AssetId != assetId).ToList(); + } + } + bool isInLoadQueue = false; + + // Could just invalidate the cache, but we're going to have to rebuild it in just a moment, + // and we have enough information to mutate it properly. + if (!isInActiveRequests && !isInRequestLoadQueue && !isInLoadQueue) + { + m_IsLoadingMemo.Remove(assetId); + } + } + + return !IsLoading(assetId); + } + + /// Downloads models referenced by the passed sketch. + /// Pass the reason this is happening. + /// TODO: maybe annotate the download request so we can choose whether they turn + /// into model loads? + public void PrecacheModels(SceneFileInfo sceneFileInfo, string reason) + { + if (string.IsNullOrEmpty(App.Config.GoogleSecrets?.ApiKey)) + { + return; + } + StartCoroutine(PrecacheModelsCoroutine(sceneFileInfo, reason)); + } + + /// Waits for the json data to be read on a background thread, and then executes a precache + /// coroutine for each found asset. + private IEnumerator PrecacheModelsCoroutine(SceneFileInfo sceneFileInfo, string reason) + { + var getIdsFuture = new Future>(() => GetModelIds(sceneFileInfo)); + List ids; + while (true) + { + try + { + if (getIdsFuture.TryGetResult(out ids)) { break; } + } + catch (FutureFailed e) + { + throw new Exception($"While reading {sceneFileInfo}", e); + } + yield return null; + } + + if (ids == null) { yield break; } + List> precacheCoroutines = new List>(); + // Only trigger off one precache routine per frame. + foreach (string id in ids) + { + if (m_ModelsByAssetId.ContainsKey(id)) + { + // Already cached + continue; + } + if (!FileUtils.InitializeDirectory(GetCacheDirectoryForAsset(id))) + { + continue; + } + precacheCoroutines.Add(PrecacheCoroutine( + VrAssetService.m_Instance.GetAsset(id, VrAssetFormat.GLTF2, reason))); + yield return null; + } + + var cr = CoroutineUtil.CompleteAllCoroutines(precacheCoroutines); + while (cr.MoveNext()) + { + yield return cr.Current; + } + } + + /// Returns all non-null asset ids from the passed sketch's metadata. + /// null return value means "empty list". + /// Raises exception on error. + private static List GetModelIds(SceneFileInfo sceneFileInfo) + { + // Json deserializing is in a separate method that doesn't access Unity objects so that it + // can be called on a thread. The json deserializing can be pretty slow and can cause + // frame drops if performed on the main thread. + Stream metadata = SaveLoadScript.GetMetadataReadStream(sceneFileInfo); + if (metadata == null) + { + if (sceneFileInfo.Exists) + { + // ??? Let's try to provoke an exception to propagate to the caller + using (var dummy = File.OpenRead(sceneFileInfo.FullPath)) { } + throw new Exception($"Unknown error opening metadata {sceneFileInfo.FullPath}"); + } + else + { + throw new Exception( + "Reading metadata from nonexistent " + + $"{sceneFileInfo.InfoType} {sceneFileInfo.HumanName}"); + } + } + using (var jsonReader = new JsonTextReader(new StreamReader(metadata))) + { + var jsonData = SaveLoadScript.m_Instance.DeserializeMetadata(jsonReader); + if (SaveLoadScript.m_Instance.LastMetadataError != null) + { + throw new Exception($"Deserialize error: {SaveLoadScript.m_Instance.LastMetadataError}"); + } + if (jsonData.ModelIndex == null) { return null; } + return jsonData.ModelIndex.Select(m => m.AssetId).Where(a => a != null).ToList(); + } + } + + // The directory for the asset must have already been created + IEnumerator PrecacheCoroutine(AssetGetter request) + { + string assetId = request.Asset.Id; + var cr = request.GetAssetCoroutine(); + while (true) + { + try + { + bool result = cr.MoveNext(); + if (!result) + { + break; + } + } + catch (VrAssetServiceException e) + { + ControllerConsoleScript.m_Instance.AddNewLine(e.Message); + Debug.LogException(e); + yield break; + } + yield return cr.Current; + } + while (!request.IsReady) { yield return null; } + request.Asset.WriteToDisk(); + string path = Path.Combine(GetCacheDirectoryForAsset(assetId), request.Asset.RootFilePath); + m_ModelsByAssetId[assetId] = new Model(Model.Location.IcosaAsset(assetId, path)); + } + + public void UpdateCatalog() + { + // Walk backwards so removal doesn't mess up our indexing. + for (int i = m_ActiveRequests.Count - 1; i >= 0; --i) + { + AssetGetter request = m_ActiveRequests[i]; + if (request.IsReady || request.IsCanceled) + { + if (request.Asset.ValidAsset) + { + if (request.Asset.WriteToDisk()) + { + string assetId = request.Asset.Id; + string path = + Path.Combine(GetCacheDirectoryForAsset(assetId), request.Asset.RootFilePath); + // TODO: This assumes PolyRawAssets are models. This may not be true in the + // future and should the VrAssetProtos.ElementType request parameter to + // VrAssetService.m_Instance.GetAsset to decide how to store and index the asset. + + // Populate map entry for this new model. + m_ModelsByAssetId[assetId] = new Model(Model.Location.IcosaAsset(assetId, path)); + + // After download the model should be loaded too, unless the request was canceled. + // TODO: this seems a littttle suspect. Just because it finished downloading, + // does that mean we still want to bring it into memory? + if (!request.IsCanceled) + { + m_RequestLoadQueue.Add( + new ModelLoadRequest( + m_ModelsByAssetId[assetId], $"{request.Reason} fetched")); + } + else + { + // Just reset, in case asset is on one of the other queues. + m_IsLoadingMemo = null; + } + } + } + else + { + Debug.LogWarning("Downloaded asset is empty " + request.Asset.RootFilePath); + } + + m_ActiveRequests.RemoveAt(i); + m_NotifyListeners = true; + } + } + + if (m_RequestLoadQueue.Count > 0 && m_LoadQueue.Count == 0) + { + // Move a single item from "request load" to "load". Too many items on the load queue + // causes bad stuttering (at least for heavy models). + var toMove = m_RequestLoadQueue[0]; + // TODO: how is it possible for m_RequestLoadQueue to contain duplicates? + m_RequestLoadQueue = m_RequestLoadQueue + .Where(elt => elt.AssetId != toMove.AssetId) + .ToList(); + m_LoadQueue.Add(toMove); + } + + // Always call this to poll the async loader. + LoadModelsInQueueAsync(); + + // Shout from the hills. + if (m_NotifyListeners) + { + if (CatalogChanged != null) + { + CatalogChanged(); + } + m_NotifyListeners = false; + } + } + + void LoadModelsInQueueAsync() + { + UnityEngine.Profiling.Profiler.BeginSample("PAC.LoadModelsInQueueAsync"); + for (int i = m_LoadQueue.Count - 1; i >= 0; --i) + { + Model model = m_LoadQueue[i].Model; + model.LoadModel(); + // TODO Back to async loading + // AsyncHelpers.RunSync(model.LoadModelAsync); + m_LoadQueue.RemoveAt(i); + m_IsLoadingMemo = null; + m_NotifyListeners = true; + // if (!model.IsLoading()) + // { + // // If the overlay is up, hitching is okay; so avoid the slow threaded image load. + // bool useThreadedImageLoad = + // OverlayManager.m_Instance.CurrentOverlayState == OverlayState.Hidden; + // // model.LoadModelAsync(useThreadedImageLoad); + // model.LoadModel(); + // } + // else + // { + // if (model.TryLoadModel(true)) + // { + // m_LoadQueue.RemoveAt(i); + // m_IsLoadingMemo = null; + // m_NotifyListeners = true; + // } + // } + } + UnityEngine.Profiling.Profiler.EndSample(); + } + + private static HashSet SetMinus(HashSet lhs, HashSet rhs) + { + var result = new HashSet(lhs); + result.ExceptWith(rhs); + return result; + } + + private IEnumerator RefreshAssetSet(IcosaSetType type) + { + List models = new List(); + // When the list is empty, make it the actual list acted upon so that results start + // showing up immediately. + if (m_AssetSetByType[type].m_Models.Count == 0) + { + m_AssetSetByType[type].m_Models = models; + } + AssetLister lister = VrAssetService.m_Instance.ListAssets(type); + bool firstPass = true; + while (lister.HasMore || firstPass) + { + firstPass = false; + using (var cr = lister.NextPage(models, m_ThumbnailSuffix)) + { + while (true) + { + try + { + if (!cr.MoveNext()) + { + break; + } + } + catch (VrAssetServiceException e) + { + ControllerConsoleScript.m_Instance.AddNewLine(e.Message); + Debug.LogException(e); + yield break; + } + yield return cr.Current; + } + } + if (models.Count == 0) + { + break; + } + } + // As the assets may already have models loaded into them, just add any new models and + // remove old ones. + var newIds = new HashSet(models.Select(m => m.AssetId)); + var oldIds = new HashSet(m_AssetSetByType[type].m_Models.Select(m => m.AssetId)); + // These must be reified; if they are left as lazy IEnumerables, O(n^2) behavior results + HashSet toAdd = SetMinus(newIds, oldIds); + HashSet toRemove = SetMinus(oldIds, newIds); + m_AssetSetByType[type].m_Models.RemoveAll(m => toRemove.Contains(m.AssetId)); + m_AssetSetByType[type].m_Models.InsertRange(0, models.Where(m => toAdd.Contains(m.AssetId))); + if (CatalogChanged != null) + { + CatalogChanged(); + } + } + + void RefreshFetchCoroutines() + { + if (App.IcosaIsLoggedIn) + { + m_AssetSetByType[IcosaSetType.User].m_RefreshRequested = true; + m_AssetSetByType[IcosaSetType.Liked].m_RefreshRequested = true; + } + else + { + AssetSet set = m_AssetSetByType[IcosaSetType.User]; + if (set.m_FetchMetadataCoroutine != null) + { + StopCoroutine(set.m_FetchMetadataCoroutine); + set.m_FetchMetadataCoroutine = null; + } + set.m_Models.Clear(); + set = m_AssetSetByType[IcosaSetType.Liked]; + if (set.m_FetchMetadataCoroutine != null) + { + StopCoroutine(set.m_FetchMetadataCoroutine); + set.m_FetchMetadataCoroutine = null; + } + set.m_Models.Clear(); + if (CatalogChanged != null) + { + CatalogChanged(); + } + } + } + + void OnProfileUpdated(OAuth2Identity _) + { + RefreshFetchCoroutines(); + } + + void OnDestroy() + { + OAuth2Identity.ProfileUpdated -= OnProfileUpdated; + } + + public int NumCloudModels(IcosaSetType type) + { + return m_AssetSetByType[type].m_Models.Count(); + } + + public AssetDetails GetPolyAsset(IcosaSetType type, int index) + { + return m_AssetSetByType[type].m_Models[index]; + } + + // Ideally we would check against the format info from Poly that we have all the required + // elements but for now we know that there should be exactly one .gltf/.gltf2 and a .bin + // Returns the filename of the .gltf/.gltf2 file, or null if not valid. + private static string ValidGltfCache(string dir, string assetId) + { + if (Directory.GetFiles(dir, "*.bin").Length == 0) + { + return null; + } + + var filesGltf1 = Directory.GetFiles(dir, "*.gltf"); + var filesGltf2 = Directory.GetFiles(dir, "*.gltf2"); + if (filesGltf1.Length + filesGltf2.Length != 1) + { + return null; + } + else if (filesGltf1.Length == 1) + { + return filesGltf1[0]; + } + else + { + return filesGltf2[0]; + } + } + + public void ClearLoadingQueue() + { + m_LoadQueue.Clear(); + m_RequestLoadQueue.Clear(); + m_IsLoadingMemo = null; + foreach (var req in m_ActiveRequests) + { + req.IsCanceled = true; + } + } + + public void UnloadUnusedModels() + { + foreach (var model in m_ModelsByAssetId.Values.Where(x => x != null && x.m_UsageCount == 0)) + { + model.UnloadModel(); + } + } + } + +} // namespace TiltBrush diff --git a/Assets/Scripts/Poly/PolyAssetCatalog.cs.meta b/Assets/Scripts/Poly/IcosaAssetCatalog.cs.meta similarity index 100% rename from Assets/Scripts/Poly/PolyAssetCatalog.cs.meta rename to Assets/Scripts/Poly/IcosaAssetCatalog.cs.meta diff --git a/Assets/Scripts/Poly/PolyRawAsset.cs b/Assets/Scripts/Poly/IcosaRawAsset.cs similarity index 93% rename from Assets/Scripts/Poly/PolyRawAsset.cs rename to Assets/Scripts/Poly/IcosaRawAsset.cs index 549b4fdc45..b845c0e100 100644 --- a/Assets/Scripts/Poly/PolyRawAsset.cs +++ b/Assets/Scripts/Poly/IcosaRawAsset.cs @@ -1,186 +1,186 @@ -// Copyright 2020 The Tilt Brush Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// 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.IO; -using System.Text.RegularExpressions; - -namespace TiltBrush -{ - - /// Class that assists in getting an asset from Poly. - public class PolyRawAsset - { - private static readonly Regex kWindowsRootedPath = new Regex("^[A-Za-z]:[/\\\\]"); - - private string m_AssetId; - private VrAssetFormat m_DesiredAssetType; - - public class ElementInfo - { - public string filePath; - public string dataURL; - public byte[] assetBytes; - } - private ElementInfo m_RootElement; - private List m_ResourceElements; - - public string Id - { - get { return m_AssetId; } - } - - public VrAssetFormat DesiredType - { - get { return m_DesiredAssetType; } - } - - public string RootFilePath - { - get { return m_RootElement.filePath; } - } - - public string RootDataURL - { - get { return m_RootElement.dataURL; } - } - - public List ResourceElements - { - get { return m_ResourceElements; } - } - - public bool ValidAsset - { - get { return m_RootElement.assetBytes != null; } - } - - public void SetRootElement(string filePath, string dataURL) - { - m_RootElement.filePath = filePath; - m_RootElement.dataURL = dataURL; - } - - public void CopyBytesToRootElement(byte[] bytes) - { - m_RootElement.assetBytes = bytes; - } - - public void AddResourceElement(string filePath, string dataURL) - { - ElementInfo info = new ElementInfo(); - info.filePath = filePath; - info.dataURL = dataURL; - m_ResourceElements.Add(info); - } - - public PolyRawAsset(string assetId, VrAssetFormat assetType) - { - m_AssetId = assetId; - m_DesiredAssetType = assetType; - m_RootElement = new ElementInfo(); - m_ResourceElements = new List(); - } - - private void RemoveFiles(List filesToRemove) - { - for (int i = 0; i < filesToRemove.Count; i++) - { - System.IO.File.Delete(filesToRemove[i]); - } - } - - /// The directory must already have been created - public bool WriteToDisk() - { - // First, iterate over everything that needs to be written to disk and verify it's valid. - // If any invalid elements are found, it's likely due to a download failure and we will abort - // the entire process. - if (m_RootElement.assetBytes == null) - { - return false; - } - ulong requiredDiskSpace = (ulong)m_RootElement.assetBytes.Length; - for (int j = 0; j < m_ResourceElements.Count; ++j) - { - if (m_ResourceElements[j].assetBytes == null) - { - // Download failed on one of the elements. - return false; - } - else - { - requiredDiskSpace += (ulong)m_ResourceElements[j].assetBytes.Length; - } - } - - // Next, check to see if we have enough disk space to write all the files. - string assetDir = App.PolyAssetCatalog.GetCacheDirectoryForAsset(m_AssetId); - if (!FileUtils.HasFreeSpace(assetDir, requiredDiskSpace / (1024 * 1024))) - { - OutputWindowScript.Error(String.Format("Out of disk space! {0} {1}", - requiredDiskSpace, m_AssetId)); - return false; - } - - // - // Next, begin writing to disk, remembering each file written to make the operation atomic. - // - var written = new List(); - if (!Directory.Exists(assetDir)) - { - UnityEngine.Debug.LogErrorFormat("Caller did not create directory for me: {0}", assetDir); - } - string rootFilePath = Path.Combine(assetDir, GetPolySanitizedFilePath(m_RootElement.filePath)); - if (!FileUtils.InitializeDirectory(Path.GetDirectoryName(rootFilePath)) || - !FileUtils.WriteBytesIgnoreExceptions(m_RootElement.assetBytes, rootFilePath)) - { - return false; - } - written.Add(rootFilePath); - - // Write all resources to disk - for (int j = 0; j < m_ResourceElements.Count; ++j) - { - string filePath = Path.Combine(assetDir, GetPolySanitizedFilePath(m_ResourceElements[j].filePath)); - if (!FileUtils.InitializeDirectory(Path.GetDirectoryName(filePath)) || - !FileUtils.WriteBytesIgnoreExceptions(m_ResourceElements[j].assetBytes, filePath)) - { - RemoveFiles(written); - return false; - } - written.Add(filePath); - } - return true; - } - - /// Returns a non-rooted path. - public static string GetPolySanitizedFilePath(string path) - { - // I'd like to change this to use FileUtils sanitize but that would involve - // clearing everyone's cache to force updating to the new naming - - // The kWindowsRootedPath check is there for compatibility with how this function used - // to work; it is not necessary for correctness. Even without the check, this - // function still always returns non-rooted paths. - if (Path.IsPathRooted(path) || kWindowsRootedPath.IsMatch(path)) - { - return Path.GetFileName(path); - } - return path; - } - } - -} // namespace TiltBrush +// Copyright 2020 The Tilt Brush Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// 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.IO; +using System.Text.RegularExpressions; + +namespace TiltBrush +{ + + /// Class that assists in getting an asset from Icosa. + public class IcosaRawAsset + { + private static readonly Regex kWindowsRootedPath = new Regex("^[A-Za-z]:[/\\\\]"); + + private string m_AssetId; + private VrAssetFormat m_DesiredAssetType; + + public class ElementInfo + { + public string filePath; + public string dataURL; + public byte[] assetBytes; + } + private ElementInfo m_RootElement; + private List m_ResourceElements; + + public string Id + { + get { return m_AssetId; } + } + + public VrAssetFormat DesiredType + { + get { return m_DesiredAssetType; } + } + + public string RootFilePath + { + get { return m_RootElement.filePath; } + } + + public string RootDataURL + { + get { return m_RootElement.dataURL; } + } + + public List ResourceElements + { + get { return m_ResourceElements; } + } + + public bool ValidAsset + { + get { return m_RootElement.assetBytes != null; } + } + + public void SetRootElement(string filePath, string dataURL) + { + m_RootElement.filePath = filePath; + m_RootElement.dataURL = dataURL; + } + + public void CopyBytesToRootElement(byte[] bytes) + { + m_RootElement.assetBytes = bytes; + } + + public void AddResourceElement(string filePath, string dataURL) + { + ElementInfo info = new ElementInfo(); + info.filePath = filePath; + info.dataURL = dataURL; + m_ResourceElements.Add(info); + } + + public IcosaRawAsset(string assetId, VrAssetFormat assetType) + { + m_AssetId = assetId; + m_DesiredAssetType = assetType; + m_RootElement = new ElementInfo(); + m_ResourceElements = new List(); + } + + private void RemoveFiles(List filesToRemove) + { + for (int i = 0; i < filesToRemove.Count; i++) + { + System.IO.File.Delete(filesToRemove[i]); + } + } + + /// The directory must already have been created + public bool WriteToDisk() + { + // First, iterate over everything that needs to be written to disk and verify it's valid. + // If any invalid elements are found, it's likely due to a download failure and we will abort + // the entire process. + if (m_RootElement.assetBytes == null) + { + return false; + } + ulong requiredDiskSpace = (ulong)m_RootElement.assetBytes.Length; + for (int j = 0; j < m_ResourceElements.Count; ++j) + { + if (m_ResourceElements[j].assetBytes == null) + { + // Download failed on one of the elements. + return false; + } + else + { + requiredDiskSpace += (ulong)m_ResourceElements[j].assetBytes.Length; + } + } + + // Next, check to see if we have enough disk space to write all the files. + string assetDir = App.IcosaAssetCatalog.GetCacheDirectoryForAsset(m_AssetId); + if (!FileUtils.HasFreeSpace(assetDir, requiredDiskSpace / (1024 * 1024))) + { + OutputWindowScript.Error(String.Format("Out of disk space! {0} {1}", + requiredDiskSpace, m_AssetId)); + return false; + } + + // + // Next, begin writing to disk, remembering each file written to make the operation atomic. + // + var written = new List(); + if (!Directory.Exists(assetDir)) + { + UnityEngine.Debug.LogErrorFormat("Caller did not create directory for me: {0}", assetDir); + } + string rootFilePath = Path.Combine(assetDir, GetPolySanitizedFilePath(m_RootElement.filePath)); + if (!FileUtils.InitializeDirectory(Path.GetDirectoryName(rootFilePath)) || + !FileUtils.WriteBytesIgnoreExceptions(m_RootElement.assetBytes, rootFilePath)) + { + return false; + } + written.Add(rootFilePath); + + // Write all resources to disk + for (int j = 0; j < m_ResourceElements.Count; ++j) + { + string filePath = Path.Combine(assetDir, GetPolySanitizedFilePath(m_ResourceElements[j].filePath)); + if (!FileUtils.InitializeDirectory(Path.GetDirectoryName(filePath)) || + !FileUtils.WriteBytesIgnoreExceptions(m_ResourceElements[j].assetBytes, filePath)) + { + RemoveFiles(written); + return false; + } + written.Add(filePath); + } + return true; + } + + /// Returns a non-rooted path. + public static string GetPolySanitizedFilePath(string path) + { + // I'd like to change this to use FileUtils sanitize but that would involve + // clearing everyone's cache to force updating to the new naming + + // The kWindowsRootedPath check is there for compatibility with how this function used + // to work; it is not necessary for correctness. Even without the check, this + // function still always returns non-rooted paths. + if (Path.IsPathRooted(path) || kWindowsRootedPath.IsMatch(path)) + { + return Path.GetFileName(path); + } + return path; + } + } + +} // namespace TiltBrush diff --git a/Assets/Scripts/Poly/PolyRawAsset.cs.meta b/Assets/Scripts/Poly/IcosaRawAsset.cs.meta similarity index 100% rename from Assets/Scripts/Poly/PolyRawAsset.cs.meta rename to Assets/Scripts/Poly/IcosaRawAsset.cs.meta diff --git a/Assets/Scripts/Save/FileSketchSet.cs b/Assets/Scripts/Save/FileSketchSet.cs index eea1d40fbd..0ea4071dc2 100644 --- a/Assets/Scripts/Save/FileSketchSet.cs +++ b/Assets/Scripts/Save/FileSketchSet.cs @@ -1,537 +1,537 @@ -// Copyright 2020 The Tilt Brush Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// 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.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using UnityEngine; - -namespace TiltBrush -{ - - public class FileSketchSet : SketchSet - { - static int ICON_LOAD_PER_FRAME = 3; - - /// Synchronously read thumbnail. Returns null on error. - public static byte[] ReadThumbnail(SceneFileInfo fileinfo) - { - using (Stream s = fileinfo.GetReadStream(TiltFile.FN_THUMBNAIL)) - { - if (s == null) { return null; } - byte[] buffer = new byte[32 * 1024]; - MemoryStream ms = new MemoryStream(); - while (true) - { - int read = s.Read(buffer, 0, buffer.Length); - if (read == 0) - { - return ms.ToArray(); - } - ms.Write(buffer, 0, read); - } - } - } - - private class FileSketch : Sketch, IComparable - { - private DiskSceneFileInfo m_FileInfo; - private Texture2D m_Icon; - private string[] m_Authors; - private bool m_bMetadataValid; - private IEnumerator m_coroutine = null; - - public SceneFileInfo SceneFileInfo - { - get { return m_FileInfo; } - } - - public string[] Authors - { - get { return m_Authors; } - } - - public Texture2D Icon - { - get { return m_Icon; } - } - - public FileSketch(DiskSceneFileInfo info) - { - m_FileInfo = info; - m_bMetadataValid = false; - - if (m_Authors == null || m_Authors.Length == 0) - { - if (m_FileInfo.HumanName.Contains(" by ")) - { - var sections = m_FileInfo.HumanName.Split(" by "); - m_Authors = new[] { sections.LastOrDefault() }; - m_FileInfo.HumanName = string.Join(" by ", sections.SkipLast(1)); - } - } - } - - public bool IconAndMetadataValid - { - get { return m_bMetadataValid; } - } - - private IEnumerable RequestLoadIconAndMetadataCoroutineThreaded() - { - var thumbFuture = new Future(() => ReadThumbnail(m_FileInfo)); - byte[] data; - while (!thumbFuture.TryGetResult(out data)) { yield return null; } - - if (data != null && data.Length > 0) - { - if (m_Icon == null) - { - m_Icon = new Texture2D(128, 128, TextureFormat.RGB24, true); - } - m_Icon.LoadImage(data); - m_Icon.Apply(); - } - else - { - // TODO: why is the icon missing/invalid? should we be noisier - // about invalid files? But RequestLoadIcon() doesn't have a - // way of indicating "not a tilt" - } - if (m_Authors == null) - { - var metadataFuture = new Future(() => m_FileInfo.ReadMetadata()); - SketchMetadata metadata; - while (!metadataFuture.TryGetResult(out metadata)) - { - yield return null; - } - if (metadata != null) - { - m_Authors = metadata.Authors; - } - else - { - if (SaveLoadScript.m_Instance.LastMetadataError != null) - { - ControllerConsoleScript.m_Instance.AddNewLine( - string.Format("Error detected in sketch '{0}'.\nTry re-saving.", - m_FileInfo.HumanName)); - Debug.LogWarning(string.Format("Error reading metadata for {0}.\n{1}", - m_FileInfo.FullPath, SaveLoadScript.m_Instance.LastMetadataError)); - } - } - } - m_bMetadataValid = true; - } - - /// Returns true if the request was fully processed. - public bool RequestLoadIconAndMetadata() - { - if (m_bMetadataValid) - { - Debug.Assert(m_coroutine == null); - return true; - } - - if (m_coroutine == null) - { - if (!m_FileInfo.Exists) - { - return true; - } - m_coroutine = RequestLoadIconAndMetadataCoroutineThreaded().GetEnumerator(); - } - - if (!m_coroutine.MoveNext()) - { - m_coroutine = null; - return true; - } - else - { - return false; - } - } - - private void AbortPendingRequest() - { - if (m_coroutine != null) - { - // This case should almost never be needed, so I'm giving it - // a rubbish, but simple and safe implementation. - while (m_coroutine.MoveNext()) - { - Thread.Sleep(0); - } - m_coroutine = null; - } - } - - public void UnloadIcon() - { - AbortPendingRequest(); - UnityEngine.Object.Destroy(m_Icon); - m_Icon = null; - m_bMetadataValid = false; - } - - public int CompareTo(FileSketch rCompareSketch) - { - return rCompareSketch.m_FileInfo.CreationTime.CompareTo(m_FileInfo.CreationTime); - } - } - - protected SketchSetType m_Type; - protected bool m_ReadyForAccess; - private List m_Sketches; - private Stack m_RequestedLoads; - private FileWatcher m_FileWatcher; - // collection of sketch paths to be added / deleted from set - // Access to these containers is synchronized, but note this is not ConcurrentQueue. - // File watcher thread is producer, main thread is consumer. - private Queue m_ToAdd; - private Queue m_ToDelete; - private bool m_ReadOnly; - private string m_SketchesPath; - - public SketchSetType Type - { - get { return m_Type; } - } - - public bool IsReadyForAccess - { - get { return m_ReadyForAccess; } - } - - public bool IsActivelyRefreshingSketches - { - get { return false; } - } - - public bool RequestedIconsAreLoaded - { - get { return m_RequestedLoads.Count == 0; } - } - - public int NumSketches - { - get { return m_Sketches.Count; } - } - - public FileSketchSet() - { - m_Type = SketchSetType.User; - m_ReadyForAccess = false; - m_RequestedLoads = new Stack(); - m_Sketches = new List(); - m_ToAdd = Queue.Synchronized(new Queue()); - m_ToDelete = Queue.Synchronized(new Queue()); - m_ReadOnly = false; - m_SketchesPath = App.UserSketchPath(); - } - - public FileSketchSet(string path) - { - m_Type = SketchSetType.Curated; - m_ReadyForAccess = false; - m_RequestedLoads = new Stack(); - m_Sketches = new List(); - m_ToAdd = Queue.Synchronized(new Queue()); - m_ToDelete = Queue.Synchronized(new Queue()); - m_ReadOnly = true; - m_SketchesPath = path; - } - - public bool IsSketchIndexValid(int iIndex) - { - return (iIndex >= 0 && iIndex < m_Sketches.Count); - } - - // Returns true if metadata.json has been deserialized. - // Icon texture and SketchMetadata may be null if invalid. - public bool GetSketchIcon(int iSketchIndex, out Texture2D icon, out string[] authors, - out string description) - { - description = null; - if (!IsSketchIndexValid(iSketchIndex)) - { - Debug.Log("SketchCatalog Error: Invalid index for Sketch Metadata requested."); - icon = null; - authors = null; - return false; - } - else if (!m_Sketches[iSketchIndex].IconAndMetadataValid) - { - icon = null; - authors = null; - return false; - } - - icon = m_Sketches[iSketchIndex].Icon; - authors = m_Sketches[iSketchIndex].Authors; - return true; - } - - public SceneFileInfo GetSketchSceneFileInfo(int iSketchIndex) - { - if (!IsSketchIndexValid(iSketchIndex)) - { - Debug.Log("SketchCatalog Error: Invalid index for Sketch SceneFileInfo requested."); - return null; - } - return m_Sketches[iSketchIndex].SceneFileInfo; - } - - public string GetSketchName(int iSketchIndex) - { - if (!IsSketchIndexValid(iSketchIndex)) - { - Debug.Log("SketchCatalog Error: Invalid index for Sketch Name requested."); - return null; - } - return m_Sketches[iSketchIndex].SceneFileInfo.HumanName; - } - - public void PrecacheSketchModels(int iSketchIndex) - { - if (!IsSketchIndexValid(iSketchIndex)) - { - Debug.Log("SketchCatalog Error: Invalid index for Sketch Name requested."); - return; - } - App.PolyAssetCatalog.PrecacheModels( - m_Sketches[iSketchIndex].SceneFileInfo, $"FileSketchSet {iSketchIndex}"); - } - - public virtual void DeleteSketch(int toDelete) - { - // Not sure why we need the validity check; but if any are invalid, it - // is a serious error and we shouldn't touch anything - if (!IsSketchIndexValid(toDelete)) - { - Debug.Assert(false, "Sketch set index out of range"); - return; - } - - // Notify our file watcher to make sure it got the memo this sketch was deleted. - m_FileWatcher.NotifyDelete(m_Sketches[toDelete].SceneFileInfo.FullPath); - - // Notify the drive sketchset as the deleted file may now be visible there. - var driveSet = SketchCatalog.m_Instance.GetSet(SketchSetType.Drive); - if (driveSet != null) - { - driveSet.NotifySketchChanged(m_Sketches[toDelete].SceneFileInfo.FullPath); - } - - m_Sketches[toDelete].SceneFileInfo.Delete(); - } - - public virtual void RenameSketch(int toRename, string newName) - { - // Notify our file watcher to make sure it got the memo this sketch was deleted. - m_FileWatcher.NotifyDelete(m_Sketches[toRename].SceneFileInfo.FullPath); - - // Notify the drive sketchset as the deleted file may now be visible there. - var driveSet = SketchCatalog.m_Instance.GetSet(SketchSetType.Drive); - if (driveSet != null) - { - driveSet.NotifySketchChanged(m_Sketches[toRename].SceneFileInfo.FullPath); - } - - var newPath = m_Sketches[toRename].SceneFileInfo.Rename(newName); - - m_FileWatcher.NotifyCreated(newPath); - - } - - public virtual void Init() - { - ProcessDirectory(m_SketchesPath); - m_ReadyForAccess = true; - - // No real reason to do this; SaveLoadScript creates the directory itself - try { Directory.CreateDirectory(m_SketchesPath); } - catch (IOException) { } - catch (UnauthorizedAccessException) { } - - if (Directory.Exists(m_SketchesPath) && !m_ReadOnly) - { - m_FileWatcher = new FileWatcher(m_SketchesPath, "*" + SaveLoadScript.TILT_SUFFIX); - // TODO: improve robustness. Using Created works for typical copy and move operations, but - // doesn't handle e.g. streaming file. - // Note: Renamed event not implemented on OS X, so we rely on Deleted + Created - // If we ever start doing something special (like warning the user) with deleted or added, we - // may need to add an explicit 'changed' queue, but delete then create works fine for now. - m_FileWatcher.FileCreated += (object sender, FileSystemEventArgs e) => - { - m_ToAdd.Enqueue(e.FullPath); - }; - m_FileWatcher.FileDeleted += (object sender, FileSystemEventArgs e) => - { - m_ToDelete.Enqueue(e.FullPath); - }; - m_FileWatcher.FileChanged += (object sender, FileSystemEventArgs e) => - { - m_ToDelete.Enqueue(e.FullPath); - m_ToAdd.Enqueue(e.FullPath); - }; - m_FileWatcher.EnableRaisingEvents = true; - } - } - - /// Requests that we (as asynchronously as possible) load thumbnail icons - /// and metadata for the specified sketches. - /// - /// Takes ownership of the list. - public void RequestOnlyLoadedMetadata(List requests) - { - DumpIconTextures(); // This clears out any pending requests - m_RequestedLoads.Clear(); - - requests.Reverse(); - foreach (var iSketch in requests) - { - Debug.Assert(IsSketchIndexValid(iSketch)); - m_RequestedLoads.Push(iSketch); - } - } - - void DumpIconTextures() - { - for (int i = 0; i < m_Sketches.Count; ++i) - { - m_Sketches[i].UnloadIcon(); - } - Resources.UnloadUnusedAssets(); - } - - private Stack Update__working = new Stack(); - - public void NotifySketchCreated(string fullpath) - { - m_FileWatcher.NotifyCreated(fullpath); - } - - public void NotifySketchChanged(string fullpath) - { - m_FileWatcher.NotifyChanged(fullpath); - } - - public void RequestRefresh() - { - } - - public void Update() - { - // process async directory changes from file system watcher - // note: code here assumes we're the only consumer - bool changedEvent = false; - while (m_ToDelete.Count > 0) - { - string path = (string)m_ToDelete.Dequeue(); - if (RemoveSketchByPath(path)) - { - changedEvent = true; - } - } - // be nice and only add one sketch per frame, since we're validating header - if (m_ToAdd.Count > 0) - { - string path = (string)m_ToAdd.Dequeue(); - var fileInfo = new DiskSceneFileInfo(path, readOnly: m_ReadOnly); - if (fileInfo.IsHeaderValid()) - { - AddSketchToSet(fileInfo); - m_Sketches.Sort(); - changedEvent = true; - } - } - if (changedEvent) - { - OnChanged(); - } - - // Grab a few units of work - var working = Update__working; // = new Stack(); - Debug.Assert(working.Count == 0); - for (int i = 0; i < ICON_LOAD_PER_FRAME && m_RequestedLoads.Count > 0; ++i) - { - working.Push(m_RequestedLoads.Pop()); - } - - // Process work (perhaps generating future work) - while (working.Count > 0) - { - int iSketch = working.Pop(); - if (!m_Sketches[iSketch].RequestLoadIconAndMetadata()) - { - m_RequestedLoads.Push(iSketch); - } - } - } - - private void ProcessDirectory(string path) - { - var di = new DirectoryInfo(path); - if (!di.Exists) - { - return; - } - foreach (DiskSceneFileInfo info in SaveLoadScript.IterScenes(di, m_ReadOnly)) - { - //don't add bogus files to the catalog - if (info.IsHeaderValid()) - { - AddSketchToSet(info); - } - } - m_Sketches.Sort(); - } - - protected void AddSketchToSet(DiskSceneFileInfo rInfo) - { - m_Sketches.Add(new FileSketch(rInfo)); - } - - /// Remove sketch with given path from set, returning false if no such sketch. - private bool RemoveSketchByPath(string path) - { - // TODO: avoid this O(n) call by changing SketchSet API to not be index-based - int index = m_Sketches.FindIndex(sketch => sketch.SceneFileInfo.FullPath == path); - if (index != -1) - { - m_Sketches.RemoveAt(index); - return true; - } - else - { - return false; - } - } - - public event Action OnChanged = delegate { }; - - public event Action OnSketchRefreshingChanged - { - add { } - remove { } - } - - } -} // namespace TiltBrush +// Copyright 2020 The Tilt Brush Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// 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.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using UnityEngine; + +namespace TiltBrush +{ + + public class FileSketchSet : SketchSet + { + static int ICON_LOAD_PER_FRAME = 3; + + /// Synchronously read thumbnail. Returns null on error. + public static byte[] ReadThumbnail(SceneFileInfo fileinfo) + { + using (Stream s = fileinfo.GetReadStream(TiltFile.FN_THUMBNAIL)) + { + if (s == null) { return null; } + byte[] buffer = new byte[32 * 1024]; + MemoryStream ms = new MemoryStream(); + while (true) + { + int read = s.Read(buffer, 0, buffer.Length); + if (read == 0) + { + return ms.ToArray(); + } + ms.Write(buffer, 0, read); + } + } + } + + private class FileSketch : Sketch, IComparable + { + private DiskSceneFileInfo m_FileInfo; + private Texture2D m_Icon; + private string[] m_Authors; + private bool m_bMetadataValid; + private IEnumerator m_coroutine = null; + + public SceneFileInfo SceneFileInfo + { + get { return m_FileInfo; } + } + + public string[] Authors + { + get { return m_Authors; } + } + + public Texture2D Icon + { + get { return m_Icon; } + } + + public FileSketch(DiskSceneFileInfo info) + { + m_FileInfo = info; + m_bMetadataValid = false; + + if (m_Authors == null || m_Authors.Length == 0) + { + if (m_FileInfo.HumanName.Contains(" by ")) + { + var sections = m_FileInfo.HumanName.Split(" by "); + m_Authors = new[] { sections.LastOrDefault() }; + m_FileInfo.HumanName = string.Join(" by ", sections.SkipLast(1)); + } + } + } + + public bool IconAndMetadataValid + { + get { return m_bMetadataValid; } + } + + private IEnumerable RequestLoadIconAndMetadataCoroutineThreaded() + { + var thumbFuture = new Future(() => ReadThumbnail(m_FileInfo)); + byte[] data; + while (!thumbFuture.TryGetResult(out data)) { yield return null; } + + if (data != null && data.Length > 0) + { + if (m_Icon == null) + { + m_Icon = new Texture2D(128, 128, TextureFormat.RGB24, true); + } + m_Icon.LoadImage(data); + m_Icon.Apply(); + } + else + { + // TODO: why is the icon missing/invalid? should we be noisier + // about invalid files? But RequestLoadIcon() doesn't have a + // way of indicating "not a tilt" + } + if (m_Authors == null) + { + var metadataFuture = new Future(() => m_FileInfo.ReadMetadata()); + SketchMetadata metadata; + while (!metadataFuture.TryGetResult(out metadata)) + { + yield return null; + } + if (metadata != null) + { + m_Authors = metadata.Authors; + } + else + { + if (SaveLoadScript.m_Instance.LastMetadataError != null) + { + ControllerConsoleScript.m_Instance.AddNewLine( + string.Format("Error detected in sketch '{0}'.\nTry re-saving.", + m_FileInfo.HumanName)); + Debug.LogWarning(string.Format("Error reading metadata for {0}.\n{1}", + m_FileInfo.FullPath, SaveLoadScript.m_Instance.LastMetadataError)); + } + } + } + m_bMetadataValid = true; + } + + /// Returns true if the request was fully processed. + public bool RequestLoadIconAndMetadata() + { + if (m_bMetadataValid) + { + Debug.Assert(m_coroutine == null); + return true; + } + + if (m_coroutine == null) + { + if (!m_FileInfo.Exists) + { + return true; + } + m_coroutine = RequestLoadIconAndMetadataCoroutineThreaded().GetEnumerator(); + } + + if (!m_coroutine.MoveNext()) + { + m_coroutine = null; + return true; + } + else + { + return false; + } + } + + private void AbortPendingRequest() + { + if (m_coroutine != null) + { + // This case should almost never be needed, so I'm giving it + // a rubbish, but simple and safe implementation. + while (m_coroutine.MoveNext()) + { + Thread.Sleep(0); + } + m_coroutine = null; + } + } + + public void UnloadIcon() + { + AbortPendingRequest(); + UnityEngine.Object.Destroy(m_Icon); + m_Icon = null; + m_bMetadataValid = false; + } + + public int CompareTo(FileSketch rCompareSketch) + { + return rCompareSketch.m_FileInfo.CreationTime.CompareTo(m_FileInfo.CreationTime); + } + } + + protected SketchSetType m_Type; + protected bool m_ReadyForAccess; + private List m_Sketches; + private Stack m_RequestedLoads; + private FileWatcher m_FileWatcher; + // collection of sketch paths to be added / deleted from set + // Access to these containers is synchronized, but note this is not ConcurrentQueue. + // File watcher thread is producer, main thread is consumer. + private Queue m_ToAdd; + private Queue m_ToDelete; + private bool m_ReadOnly; + private string m_SketchesPath; + + public SketchSetType Type + { + get { return m_Type; } + } + + public bool IsReadyForAccess + { + get { return m_ReadyForAccess; } + } + + public bool IsActivelyRefreshingSketches + { + get { return false; } + } + + public bool RequestedIconsAreLoaded + { + get { return m_RequestedLoads.Count == 0; } + } + + public int NumSketches + { + get { return m_Sketches.Count; } + } + + public FileSketchSet() + { + m_Type = SketchSetType.User; + m_ReadyForAccess = false; + m_RequestedLoads = new Stack(); + m_Sketches = new List(); + m_ToAdd = Queue.Synchronized(new Queue()); + m_ToDelete = Queue.Synchronized(new Queue()); + m_ReadOnly = false; + m_SketchesPath = App.UserSketchPath(); + } + + public FileSketchSet(string path) + { + m_Type = SketchSetType.Curated; + m_ReadyForAccess = false; + m_RequestedLoads = new Stack(); + m_Sketches = new List(); + m_ToAdd = Queue.Synchronized(new Queue()); + m_ToDelete = Queue.Synchronized(new Queue()); + m_ReadOnly = true; + m_SketchesPath = path; + } + + public bool IsSketchIndexValid(int iIndex) + { + return (iIndex >= 0 && iIndex < m_Sketches.Count); + } + + // Returns true if metadata.json has been deserialized. + // Icon texture and SketchMetadata may be null if invalid. + public bool GetSketchIcon(int iSketchIndex, out Texture2D icon, out string[] authors, + out string description) + { + description = null; + if (!IsSketchIndexValid(iSketchIndex)) + { + Debug.Log("SketchCatalog Error: Invalid index for Sketch Metadata requested."); + icon = null; + authors = null; + return false; + } + else if (!m_Sketches[iSketchIndex].IconAndMetadataValid) + { + icon = null; + authors = null; + return false; + } + + icon = m_Sketches[iSketchIndex].Icon; + authors = m_Sketches[iSketchIndex].Authors; + return true; + } + + public SceneFileInfo GetSketchSceneFileInfo(int iSketchIndex) + { + if (!IsSketchIndexValid(iSketchIndex)) + { + Debug.Log("SketchCatalog Error: Invalid index for Sketch SceneFileInfo requested."); + return null; + } + return m_Sketches[iSketchIndex].SceneFileInfo; + } + + public string GetSketchName(int iSketchIndex) + { + if (!IsSketchIndexValid(iSketchIndex)) + { + Debug.Log("SketchCatalog Error: Invalid index for Sketch Name requested."); + return null; + } + return m_Sketches[iSketchIndex].SceneFileInfo.HumanName; + } + + public void PrecacheSketchModels(int iSketchIndex) + { + if (!IsSketchIndexValid(iSketchIndex)) + { + Debug.Log("SketchCatalog Error: Invalid index for Sketch Name requested."); + return; + } + App.IcosaAssetCatalog.PrecacheModels( + m_Sketches[iSketchIndex].SceneFileInfo, $"FileSketchSet {iSketchIndex}"); + } + + public virtual void DeleteSketch(int toDelete) + { + // Not sure why we need the validity check; but if any are invalid, it + // is a serious error and we shouldn't touch anything + if (!IsSketchIndexValid(toDelete)) + { + Debug.Assert(false, "Sketch set index out of range"); + return; + } + + // Notify our file watcher to make sure it got the memo this sketch was deleted. + m_FileWatcher.NotifyDelete(m_Sketches[toDelete].SceneFileInfo.FullPath); + + // Notify the drive sketchset as the deleted file may now be visible there. + var driveSet = SketchCatalog.m_Instance.GetSet(SketchSetType.Drive); + if (driveSet != null) + { + driveSet.NotifySketchChanged(m_Sketches[toDelete].SceneFileInfo.FullPath); + } + + m_Sketches[toDelete].SceneFileInfo.Delete(); + } + + public virtual void RenameSketch(int toRename, string newName) + { + // Notify our file watcher to make sure it got the memo this sketch was deleted. + m_FileWatcher.NotifyDelete(m_Sketches[toRename].SceneFileInfo.FullPath); + + // Notify the drive sketchset as the deleted file may now be visible there. + var driveSet = SketchCatalog.m_Instance.GetSet(SketchSetType.Drive); + if (driveSet != null) + { + driveSet.NotifySketchChanged(m_Sketches[toRename].SceneFileInfo.FullPath); + } + + var newPath = m_Sketches[toRename].SceneFileInfo.Rename(newName); + + m_FileWatcher.NotifyCreated(newPath); + + } + + public virtual void Init() + { + ProcessDirectory(m_SketchesPath); + m_ReadyForAccess = true; + + // No real reason to do this; SaveLoadScript creates the directory itself + try { Directory.CreateDirectory(m_SketchesPath); } + catch (IOException) { } + catch (UnauthorizedAccessException) { } + + if (Directory.Exists(m_SketchesPath) && !m_ReadOnly) + { + m_FileWatcher = new FileWatcher(m_SketchesPath, "*" + SaveLoadScript.TILT_SUFFIX); + // TODO: improve robustness. Using Created works for typical copy and move operations, but + // doesn't handle e.g. streaming file. + // Note: Renamed event not implemented on OS X, so we rely on Deleted + Created + // If we ever start doing something special (like warning the user) with deleted or added, we + // may need to add an explicit 'changed' queue, but delete then create works fine for now. + m_FileWatcher.FileCreated += (object sender, FileSystemEventArgs e) => + { + m_ToAdd.Enqueue(e.FullPath); + }; + m_FileWatcher.FileDeleted += (object sender, FileSystemEventArgs e) => + { + m_ToDelete.Enqueue(e.FullPath); + }; + m_FileWatcher.FileChanged += (object sender, FileSystemEventArgs e) => + { + m_ToDelete.Enqueue(e.FullPath); + m_ToAdd.Enqueue(e.FullPath); + }; + m_FileWatcher.EnableRaisingEvents = true; + } + } + + /// Requests that we (as asynchronously as possible) load thumbnail icons + /// and metadata for the specified sketches. + /// + /// Takes ownership of the list. + public void RequestOnlyLoadedMetadata(List requests) + { + DumpIconTextures(); // This clears out any pending requests + m_RequestedLoads.Clear(); + + requests.Reverse(); + foreach (var iSketch in requests) + { + Debug.Assert(IsSketchIndexValid(iSketch)); + m_RequestedLoads.Push(iSketch); + } + } + + void DumpIconTextures() + { + for (int i = 0; i < m_Sketches.Count; ++i) + { + m_Sketches[i].UnloadIcon(); + } + Resources.UnloadUnusedAssets(); + } + + private Stack Update__working = new Stack(); + + public void NotifySketchCreated(string fullpath) + { + m_FileWatcher.NotifyCreated(fullpath); + } + + public void NotifySketchChanged(string fullpath) + { + m_FileWatcher.NotifyChanged(fullpath); + } + + public void RequestRefresh() + { + } + + public void Update() + { + // process async directory changes from file system watcher + // note: code here assumes we're the only consumer + bool changedEvent = false; + while (m_ToDelete.Count > 0) + { + string path = (string)m_ToDelete.Dequeue(); + if (RemoveSketchByPath(path)) + { + changedEvent = true; + } + } + // be nice and only add one sketch per frame, since we're validating header + if (m_ToAdd.Count > 0) + { + string path = (string)m_ToAdd.Dequeue(); + var fileInfo = new DiskSceneFileInfo(path, readOnly: m_ReadOnly); + if (fileInfo.IsHeaderValid()) + { + AddSketchToSet(fileInfo); + m_Sketches.Sort(); + changedEvent = true; + } + } + if (changedEvent) + { + OnChanged(); + } + + // Grab a few units of work + var working = Update__working; // = new Stack(); + Debug.Assert(working.Count == 0); + for (int i = 0; i < ICON_LOAD_PER_FRAME && m_RequestedLoads.Count > 0; ++i) + { + working.Push(m_RequestedLoads.Pop()); + } + + // Process work (perhaps generating future work) + while (working.Count > 0) + { + int iSketch = working.Pop(); + if (!m_Sketches[iSketch].RequestLoadIconAndMetadata()) + { + m_RequestedLoads.Push(iSketch); + } + } + } + + private void ProcessDirectory(string path) + { + var di = new DirectoryInfo(path); + if (!di.Exists) + { + return; + } + foreach (DiskSceneFileInfo info in SaveLoadScript.IterScenes(di, m_ReadOnly)) + { + //don't add bogus files to the catalog + if (info.IsHeaderValid()) + { + AddSketchToSet(info); + } + } + m_Sketches.Sort(); + } + + protected void AddSketchToSet(DiskSceneFileInfo rInfo) + { + m_Sketches.Add(new FileSketch(rInfo)); + } + + /// Remove sketch with given path from set, returning false if no such sketch. + private bool RemoveSketchByPath(string path) + { + // TODO: avoid this O(n) call by changing SketchSet API to not be index-based + int index = m_Sketches.FindIndex(sketch => sketch.SceneFileInfo.FullPath == path); + if (index != -1) + { + m_Sketches.RemoveAt(index); + return true; + } + else + { + return false; + } + } + + public event Action OnChanged = delegate { }; + + public event Action OnSketchRefreshingChanged + { + add { } + remove { } + } + + } +} // namespace TiltBrush diff --git a/Assets/Scripts/Save/MetadataUtils.cs b/Assets/Scripts/Save/MetadataUtils.cs index cbd034561d..9ac4232c5a 100644 --- a/Assets/Scripts/Save/MetadataUtils.cs +++ b/Assets/Scripts/Save/MetadataUtils.cs @@ -1,446 +1,446 @@ -// Copyright 2020 The Tilt Brush Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// 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 System.Collections.Generic; -using System.IO; -using System.Linq; - -namespace TiltBrush -{ - public static class MetadataUtils - { - public struct WidgetMetadata - { - public TrTransform xf; - public string subtree; - public bool pinned; - public bool tinted; - public uint groupId; - public int layerId; - public bool twoSided; - } - - /// Sanitizes potentially-invalid data coming from the .tilt file. - /// Returns an array of valid TrTransforms; may return the input array. - public static TrTransform[] Sanitize(TrTransform[] data) - { - if (data != null) - { - for (int i = 0; i < data.Length; ++i) - { - if (!data[i].IsFinite()) - { - Debug.LogWarningFormat("Found non-finite TrTransform: {0}", data[i]); - return data.Where(xf => xf.IsFinite()).ToArray(); - } - } - } - - return data; - } - - private static float ByTranslation(WidgetMetadata meta) - { - return Vector3.Dot(meta.xf.translation, new Vector3(256 * 256, 256, 1)); - } - - private static float ByTranslation(TrTransform xf) - { - return Vector3.Dot(xf.translation, new Vector3(256 * 256, 256, 1)); - } - - private static string ByModelLocation(TiltModels75 models) - { - if (models.AssetId != null) - { - return "AssetId:" + models.AssetId; - } - else if (models.FilePath != null) - { - return "FilePath:" + models.FilePath; - } - Debug.LogWarning("Attempted to save model without asset id or filepath"); - return ""; - } - - public static CameraPathMetadata[] GetCameraPaths() - { - return WidgetManager.m_Instance.CameraPathWidgets - .Where(cpw => cpw.WidgetScript.ShouldSerialize()) - .Select(cpw => cpw.WidgetScript.AsSerializable()) - .ToArray(); - } - - public static LayerMetadata[] GetLayers() - { - return App.Scene.LayerCanvasesSerialized(); - } - - public static TiltModels75[] GetTiltModels(GroupIdMapping groupIdMapping) - { - var widgets = - WidgetManager.m_Instance.ModelWidgets.Where(w => w.gameObject.activeSelf).ToArray(); - if (widgets.Length == 0 && !ModelCatalog.m_Instance.MissingModels.Any()) - { - return null; - } - var widgetModels = widgets.Select(w => w.Model).Distinct(); - - Dictionary> modelLocationMap = - new Dictionary>(); - foreach (var model in widgetModels) - { - modelLocationMap[model.GetLocation()] = new List(); - } - foreach (var widget in widgets) - { - WidgetMetadata newEntry = new WidgetMetadata(); - newEntry.xf = widget.GetSaveTransform(); - newEntry.subtree = widget.Subtree; - newEntry.pinned = widget.Pinned; - newEntry.groupId = groupIdMapping.GetId(widget.Group); - newEntry.layerId = App.Scene.GetIndexOfCanvas(widget.Canvas); - modelLocationMap[widget.Model.GetLocation()].Add(newEntry); - } - - List models = new List(); - foreach (var elem in modelLocationMap) - { - var val = new TiltModels75 - { - Location = elem.Key, - }; - - // Order and align the metadata. - WidgetMetadata[] ordered = elem.Value.OrderBy(ByTranslation).ToArray(); - val.PinStates = new bool[ordered.Length]; - val.Subtrees = new string[ordered.Length]; - val.RawTransforms = new TrTransform[ordered.Length]; - val.GroupIds = new uint[ordered.Length]; - val.LayerIds = new int[ordered.Length]; - for (int i = 0; i < ordered.Length; ++i) - { - val.Subtrees[i] = ordered[i].subtree; - val.PinStates[i] = ordered[i].pinned; - val.RawTransforms[i] = ordered[i].xf; - val.GroupIds[i] = ordered[i].groupId; - val.LayerIds[i] = ordered[i].layerId; - } - models.Add(val); - } - - return models - .Concat(ModelCatalog.m_Instance.MissingModels) - .OrderBy(ByModelLocation).ToArray(); - } - - public static TiltVideo[] GetTiltVideos(GroupIdMapping groupIdMapping) - { - return WidgetManager.m_Instance.VideoWidgets.Where(x => x.gameObject.activeSelf).Select(x => ConvertVideoToTiltVideo(x)).ToArray(); - - TiltVideo ConvertVideoToTiltVideo(VideoWidget widget) - { - TiltVideo video = new TiltVideo - { - // Annoyingly Images now use forward slash and a leading dot. So this is inconsistent. - // Switching videos would have led to backwards incompatible changes in .tilt files - // or an annoying legacy - FilePath = widget.Video.PersistentPath, - AspectRatio = widget.Video.Aspect, - Pinned = widget.Pinned, - Transform = widget.SaveTransform, - GroupId = groupIdMapping.GetId(widget.Group), - LayerId = App.Scene.GetIndexOfCanvas(widget.Canvas), - TwoSided = widget.TwoSided - }; - if (widget.VideoController != null) - { - video.Paused = !widget.VideoController.Playing; - video.Time = widget.VideoController.Time; - video.Volume = widget.VideoController.Volume; - } - return video; - } - } - - public static Guides[] GetGuideIndex(GroupIdMapping groupIdMapping) - { - var stencils = - WidgetManager.m_Instance.StencilWidgets.Where(s => s.gameObject.activeSelf).ToList(); - if (stencils.Count == 0) - { - return null; - } - Dictionary> guides = - new Dictionary>(); - foreach (var stencil in stencils) - { - if (!guides.ContainsKey(stencil.Type)) - { - guides[stencil.Type] = new List(); - } - guides[stencil.Type].Add(stencil.GetSaveState(groupIdMapping)); - } - List guideIndex = new List(); - foreach (var elem in guides) - { - guideIndex.Add(new Guides - { - Type = elem.Key, - States = elem.Value.OrderBy(s => ByTranslation(s.Transform)).ToArray() - }); - } - return guideIndex.OrderBy(g => g.Type).ToArray(); - } - - public static TiltLights[] GetTiltLights(GroupIdMapping groupIdMapping) - { - var imports = WidgetManager.m_Instance.LightWidgets - .Where(w => w.gameObject.activeSelf).ToArray(); - if (imports.Length == 0) - { - return null; - } - - var lightIndex = new List(); - foreach (var lightWidget in imports) - { - var light = lightWidget.GetComponentInChildren(); - var newEntry = new TiltLights(); - newEntry.Transform = lightWidget.GetSaveTransform(); - newEntry.Pinned = lightWidget.Pinned; - newEntry.GroupId = groupIdMapping.GetId(lightWidget.Group); - newEntry.LayerId = App.Scene.GetIndexOfCanvas(lightWidget.Canvas); - - newEntry.PunctualLightType = light.type; - newEntry.Intensity = light.intensity; - newEntry.LightColor = light.color; - - if (light.type == LightType.Spot) - { - newEntry.InnerConeAngle = light.innerSpotAngle; - newEntry.OuterConeAngle = light.spotAngle; - } - - if (light.type == LightType.Point || light.type == LightType.Spot) - { - newEntry.Range = light.range; - } - - lightIndex.Add(newEntry); - } - return lightIndex.ToArray(); - } - - public static TiltImages75[] GetTiltImages(GroupIdMapping groupIdMapping) - { - var imports = WidgetManager.m_Instance.ImageWidgets - .Where(w => w.gameObject.activeSelf).ToArray(); - if (imports.Length == 0) - { - return null; - } - - // From the list of image widgets in the sketch, create a map that contains a unique - // entry per image, with associated metadata (transform and pin state) stored as arrays. - Dictionary> imagesByPath = - new Dictionary>(); - Dictionary aspectRatios = new Dictionary(); - foreach (var image in imports) - { - string path = image.RelativePath; - if (image.AspectRatio == null) - { - Debug.LogError("Trying to save partially-initialized image {fileName}"); - } - if (!imagesByPath.ContainsKey(path)) - { - imagesByPath[path] = new List(); - aspectRatios[path] = image.AspectRatio ?? 1; - } - WidgetMetadata newEntry = new WidgetMetadata(); - newEntry.xf = image.SaveTransform; - newEntry.pinned = image.Pinned; - newEntry.tinted = image.UseLegacyTint; - newEntry.groupId = groupIdMapping.GetId(image.Group); - newEntry.layerId = App.Scene.GetIndexOfCanvas(image.Canvas); - newEntry.twoSided = image.TwoSided; - imagesByPath[path].Add(newEntry); - } - - // Build the save metadata from our unique map. - List imageIndex = new List(); - foreach (var elem in imagesByPath) - { - var val = new TiltImages75 - { - FilePath = elem.Key, - FileName = Path.GetFileName(elem.Key), - AspectRatio = aspectRatios[elem.Key] - }; - - // Order and align the metadata. - WidgetMetadata[] ordered = - elem.Value.OrderBy(ByTranslation).ToArray(); - val.PinStates = new bool[ordered.Length]; - val.TintStates = new bool[ordered.Length]; - val.Transforms = new TrTransform[ordered.Length]; - val.GroupIds = new uint[ordered.Length]; - val.LayerIds = new int[ordered.Length]; - val.TwoSidedFlags = new bool[ordered.Length]; - for (int i = 0; i < ordered.Length; ++i) - { - val.PinStates[i] = ordered[i].pinned; - val.TintStates[i] = ordered[i].tinted; - val.Transforms[i] = ordered[i].xf; - val.GroupIds[i] = ordered[i].groupId; - val.LayerIds[i] = ordered[i].layerId; - val.TwoSidedFlags[i] = ordered[i].twoSided; - } - imageIndex.Add(val); - } - return imageIndex.OrderBy(i => i.FileName).ToArray(); - } - - public static void VerifyMetadataVersion(SketchMetadata data) - { - Upgrade_Set_ModelIndexInSet(data); - - if (data.SchemaVersion < 1) - { - UpgradeSchema_0to1(data); - } - if (data.SchemaVersion < 2) - { - UpgradeSchema_1to2(data); - } - } - - // Converts data.Set_deprecated[] to data.ModelIndex[].InSet - static void Upgrade_Set_ModelIndexInSet(SketchMetadata data) - { - if (data == null || data.Set_deprecated == null) - { - return; - } - - TiltModels75[] index = data.ModelIndex; - - string[] set = data.Set_deprecated; - if (index == null) { index = new TiltModels75[] { }; } - List setOnly = new List(set); - foreach (TiltModels75 m in index) - { - if (set.Contains(m.FilePath)) - { - m.InSet_deprecated = true; - setOnly.Remove(m.FilePath); - } - } - index = index.Concat(setOnly.Select(s => new TiltModels75 - { - FilePath = s, - InSet_deprecated = true - })).ToArray(); - - data.ModelIndex = index; - data.Set_deprecated = null; - } - - /// SchemaVersion 1 was released in M15. - /// It adds bool[] TiltModels75.PinStates, bool[] TiltModels75.TintStates, bool Guides.State.Pinned - static void UpgradeSchema_0to1(SketchMetadata data) - { - // Pin flags were not written out previous to v15, so default guides to pinned. - if (data.GuideIndex != null) - { - for (int i = 0; i < data.GuideIndex.Length; ++i) - { - for (int j = 0; j < data.GuideIndex[i].States.Length; ++j) - { - data.GuideIndex[i].States[j].Pinned = true; - } - } - } - - // Default images to pinned, tinted, and not grouped. - if (data.ImageIndex != null) - { - for (int i = 0; i < data.ImageIndex.Length; ++i) - { - int numXfs = data.ImageIndex[i].Transforms.Length; - data.ImageIndex[i].PinStates = Enumerable.Repeat(true, numXfs).ToArray(); - data.ImageIndex[i].TintStates = Enumerable.Repeat(true, numXfs).ToArray(); - data.ImageIndex[i].GroupIds = Enumerable.Repeat(0u, numXfs).ToArray(); - } - } - - // Default models to pinned, if they're local. Poly assets are unpinned. - if (data.ModelIndex != null) - { - for (int i = 0; i < data.ModelIndex.Length; ++i) - { - if (data.ModelIndex[i].PinStates == null) - { - int numXfs = (data.ModelIndex[i].Transforms != null) ? - data.ModelIndex[i].Transforms.Length : - data.ModelIndex[i].RawTransforms.Length; - data.ModelIndex[i].PinStates = new bool[numXfs]; - } - - for (int j = 0; j < data.ModelIndex[i].PinStates.Length; ++j) - { - data.ModelIndex[i].PinStates[j] = (data.ModelIndex[i].Location.GetLocationType() != - Model.Location.Type.PolyAssetId); - } - } - } - - data.SchemaVersion = 1; - } - - // Append value to array, creating array if necessary - static T[] SafeAppend(T[] array, T value) - { - T[] asArray = { value }; - return (array == null) ? asArray : array.Concat(asArray).ToArray(); - } - - // SchemaVersion 2: M19 - // Converts data.ModelIndex[].InSet to data.ModelIndex[].RawTransforms[] - // This changes the behavior slightly: sets are immovable, but RawTransforms[] can be unpinned. - // This essentially removes the experimental Set feature. - static void UpgradeSchema_1to2(SketchMetadata data) - { - Debug.Assert(data.SchemaVersion == 1); - if (data.ModelIndex == null) { return; } - foreach (TiltModels75 tm75 in data.ModelIndex) - { - if (!tm75.InSet_deprecated) { continue; } - // Only one of Transforms[] or RawTransforms[] can be non-null. - // Therefore, we can only append to RawTransforms[] if Transforms[] is null. - if (tm75.Transforms != null) - { - Debug.LogError("Cannot upgrade InSet if Transforms[] is non-null"); - continue; - } - tm75.InSet_deprecated = false; - tm75.m_rawTransforms = SafeAppend(tm75.m_rawTransforms, TrTransform.identity); - tm75.PinStates = SafeAppend(tm75.PinStates, true); - } - data.SchemaVersion = 2; - } - } -} // namespace TiltBrush +// Copyright 2020 The Tilt Brush Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// 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 System.Collections.Generic; +using System.IO; +using System.Linq; + +namespace TiltBrush +{ + public static class MetadataUtils + { + public struct WidgetMetadata + { + public TrTransform xf; + public string subtree; + public bool pinned; + public bool tinted; + public uint groupId; + public int layerId; + public bool twoSided; + } + + /// Sanitizes potentially-invalid data coming from the .tilt file. + /// Returns an array of valid TrTransforms; may return the input array. + public static TrTransform[] Sanitize(TrTransform[] data) + { + if (data != null) + { + for (int i = 0; i < data.Length; ++i) + { + if (!data[i].IsFinite()) + { + Debug.LogWarningFormat("Found non-finite TrTransform: {0}", data[i]); + return data.Where(xf => xf.IsFinite()).ToArray(); + } + } + } + + return data; + } + + private static float ByTranslation(WidgetMetadata meta) + { + return Vector3.Dot(meta.xf.translation, new Vector3(256 * 256, 256, 1)); + } + + private static float ByTranslation(TrTransform xf) + { + return Vector3.Dot(xf.translation, new Vector3(256 * 256, 256, 1)); + } + + private static string ByModelLocation(TiltModels75 models) + { + if (models.AssetId != null) + { + return "AssetId:" + models.AssetId; + } + else if (models.FilePath != null) + { + return "FilePath:" + models.FilePath; + } + Debug.LogWarning("Attempted to save model without asset id or filepath"); + return ""; + } + + public static CameraPathMetadata[] GetCameraPaths() + { + return WidgetManager.m_Instance.CameraPathWidgets + .Where(cpw => cpw.WidgetScript.ShouldSerialize()) + .Select(cpw => cpw.WidgetScript.AsSerializable()) + .ToArray(); + } + + public static LayerMetadata[] GetLayers() + { + return App.Scene.LayerCanvasesSerialized(); + } + + public static TiltModels75[] GetTiltModels(GroupIdMapping groupIdMapping) + { + var widgets = + WidgetManager.m_Instance.ModelWidgets.Where(w => w.gameObject.activeSelf).ToArray(); + if (widgets.Length == 0 && !ModelCatalog.m_Instance.MissingModels.Any()) + { + return null; + } + var widgetModels = widgets.Select(w => w.Model).Distinct(); + + Dictionary> modelLocationMap = + new Dictionary>(); + foreach (var model in widgetModels) + { + modelLocationMap[model.GetLocation()] = new List(); + } + foreach (var widget in widgets) + { + WidgetMetadata newEntry = new WidgetMetadata(); + newEntry.xf = widget.GetSaveTransform(); + newEntry.subtree = widget.Subtree; + newEntry.pinned = widget.Pinned; + newEntry.groupId = groupIdMapping.GetId(widget.Group); + newEntry.layerId = App.Scene.GetIndexOfCanvas(widget.Canvas); + modelLocationMap[widget.Model.GetLocation()].Add(newEntry); + } + + List models = new List(); + foreach (var elem in modelLocationMap) + { + var val = new TiltModels75 + { + Location = elem.Key, + }; + + // Order and align the metadata. + WidgetMetadata[] ordered = elem.Value.OrderBy(ByTranslation).ToArray(); + val.PinStates = new bool[ordered.Length]; + val.Subtrees = new string[ordered.Length]; + val.RawTransforms = new TrTransform[ordered.Length]; + val.GroupIds = new uint[ordered.Length]; + val.LayerIds = new int[ordered.Length]; + for (int i = 0; i < ordered.Length; ++i) + { + val.Subtrees[i] = ordered[i].subtree; + val.PinStates[i] = ordered[i].pinned; + val.RawTransforms[i] = ordered[i].xf; + val.GroupIds[i] = ordered[i].groupId; + val.LayerIds[i] = ordered[i].layerId; + } + models.Add(val); + } + + return models + .Concat(ModelCatalog.m_Instance.MissingModels) + .OrderBy(ByModelLocation).ToArray(); + } + + public static TiltVideo[] GetTiltVideos(GroupIdMapping groupIdMapping) + { + return WidgetManager.m_Instance.VideoWidgets.Where(x => x.gameObject.activeSelf).Select(x => ConvertVideoToTiltVideo(x)).ToArray(); + + TiltVideo ConvertVideoToTiltVideo(VideoWidget widget) + { + TiltVideo video = new TiltVideo + { + // Annoyingly Images now use forward slash and a leading dot. So this is inconsistent. + // Switching videos would have led to backwards incompatible changes in .tilt files + // or an annoying legacy + FilePath = widget.Video.PersistentPath, + AspectRatio = widget.Video.Aspect, + Pinned = widget.Pinned, + Transform = widget.SaveTransform, + GroupId = groupIdMapping.GetId(widget.Group), + LayerId = App.Scene.GetIndexOfCanvas(widget.Canvas), + TwoSided = widget.TwoSided + }; + if (widget.VideoController != null) + { + video.Paused = !widget.VideoController.Playing; + video.Time = widget.VideoController.Time; + video.Volume = widget.VideoController.Volume; + } + return video; + } + } + + public static Guides[] GetGuideIndex(GroupIdMapping groupIdMapping) + { + var stencils = + WidgetManager.m_Instance.StencilWidgets.Where(s => s.gameObject.activeSelf).ToList(); + if (stencils.Count == 0) + { + return null; + } + Dictionary> guides = + new Dictionary>(); + foreach (var stencil in stencils) + { + if (!guides.ContainsKey(stencil.Type)) + { + guides[stencil.Type] = new List(); + } + guides[stencil.Type].Add(stencil.GetSaveState(groupIdMapping)); + } + List guideIndex = new List(); + foreach (var elem in guides) + { + guideIndex.Add(new Guides + { + Type = elem.Key, + States = elem.Value.OrderBy(s => ByTranslation(s.Transform)).ToArray() + }); + } + return guideIndex.OrderBy(g => g.Type).ToArray(); + } + + public static TiltLights[] GetTiltLights(GroupIdMapping groupIdMapping) + { + var imports = WidgetManager.m_Instance.LightWidgets + .Where(w => w.gameObject.activeSelf).ToArray(); + if (imports.Length == 0) + { + return null; + } + + var lightIndex = new List(); + foreach (var lightWidget in imports) + { + var light = lightWidget.GetComponentInChildren(); + var newEntry = new TiltLights(); + newEntry.Transform = lightWidget.GetSaveTransform(); + newEntry.Pinned = lightWidget.Pinned; + newEntry.GroupId = groupIdMapping.GetId(lightWidget.Group); + newEntry.LayerId = App.Scene.GetIndexOfCanvas(lightWidget.Canvas); + + newEntry.PunctualLightType = light.type; + newEntry.Intensity = light.intensity; + newEntry.LightColor = light.color; + + if (light.type == LightType.Spot) + { + newEntry.InnerConeAngle = light.innerSpotAngle; + newEntry.OuterConeAngle = light.spotAngle; + } + + if (light.type == LightType.Point || light.type == LightType.Spot) + { + newEntry.Range = light.range; + } + + lightIndex.Add(newEntry); + } + return lightIndex.ToArray(); + } + + public static TiltImages75[] GetTiltImages(GroupIdMapping groupIdMapping) + { + var imports = WidgetManager.m_Instance.ImageWidgets + .Where(w => w.gameObject.activeSelf).ToArray(); + if (imports.Length == 0) + { + return null; + } + + // From the list of image widgets in the sketch, create a map that contains a unique + // entry per image, with associated metadata (transform and pin state) stored as arrays. + Dictionary> imagesByPath = + new Dictionary>(); + Dictionary aspectRatios = new Dictionary(); + foreach (var image in imports) + { + string path = image.RelativePath; + if (image.AspectRatio == null) + { + Debug.LogError("Trying to save partially-initialized image {fileName}"); + } + if (!imagesByPath.ContainsKey(path)) + { + imagesByPath[path] = new List(); + aspectRatios[path] = image.AspectRatio ?? 1; + } + WidgetMetadata newEntry = new WidgetMetadata(); + newEntry.xf = image.SaveTransform; + newEntry.pinned = image.Pinned; + newEntry.tinted = image.UseLegacyTint; + newEntry.groupId = groupIdMapping.GetId(image.Group); + newEntry.layerId = App.Scene.GetIndexOfCanvas(image.Canvas); + newEntry.twoSided = image.TwoSided; + imagesByPath[path].Add(newEntry); + } + + // Build the save metadata from our unique map. + List imageIndex = new List(); + foreach (var elem in imagesByPath) + { + var val = new TiltImages75 + { + FilePath = elem.Key, + FileName = Path.GetFileName(elem.Key), + AspectRatio = aspectRatios[elem.Key] + }; + + // Order and align the metadata. + WidgetMetadata[] ordered = + elem.Value.OrderBy(ByTranslation).ToArray(); + val.PinStates = new bool[ordered.Length]; + val.TintStates = new bool[ordered.Length]; + val.Transforms = new TrTransform[ordered.Length]; + val.GroupIds = new uint[ordered.Length]; + val.LayerIds = new int[ordered.Length]; + val.TwoSidedFlags = new bool[ordered.Length]; + for (int i = 0; i < ordered.Length; ++i) + { + val.PinStates[i] = ordered[i].pinned; + val.TintStates[i] = ordered[i].tinted; + val.Transforms[i] = ordered[i].xf; + val.GroupIds[i] = ordered[i].groupId; + val.LayerIds[i] = ordered[i].layerId; + val.TwoSidedFlags[i] = ordered[i].twoSided; + } + imageIndex.Add(val); + } + return imageIndex.OrderBy(i => i.FileName).ToArray(); + } + + public static void VerifyMetadataVersion(SketchMetadata data) + { + Upgrade_Set_ModelIndexInSet(data); + + if (data.SchemaVersion < 1) + { + UpgradeSchema_0to1(data); + } + if (data.SchemaVersion < 2) + { + UpgradeSchema_1to2(data); + } + } + + // Converts data.Set_deprecated[] to data.ModelIndex[].InSet + static void Upgrade_Set_ModelIndexInSet(SketchMetadata data) + { + if (data == null || data.Set_deprecated == null) + { + return; + } + + TiltModels75[] index = data.ModelIndex; + + string[] set = data.Set_deprecated; + if (index == null) { index = new TiltModels75[] { }; } + List setOnly = new List(set); + foreach (TiltModels75 m in index) + { + if (set.Contains(m.FilePath)) + { + m.InSet_deprecated = true; + setOnly.Remove(m.FilePath); + } + } + index = index.Concat(setOnly.Select(s => new TiltModels75 + { + FilePath = s, + InSet_deprecated = true + })).ToArray(); + + data.ModelIndex = index; + data.Set_deprecated = null; + } + + /// SchemaVersion 1 was released in M15. + /// It adds bool[] TiltModels75.PinStates, bool[] TiltModels75.TintStates, bool Guides.State.Pinned + static void UpgradeSchema_0to1(SketchMetadata data) + { + // Pin flags were not written out previous to v15, so default guides to pinned. + if (data.GuideIndex != null) + { + for (int i = 0; i < data.GuideIndex.Length; ++i) + { + for (int j = 0; j < data.GuideIndex[i].States.Length; ++j) + { + data.GuideIndex[i].States[j].Pinned = true; + } + } + } + + // Default images to pinned, tinted, and not grouped. + if (data.ImageIndex != null) + { + for (int i = 0; i < data.ImageIndex.Length; ++i) + { + int numXfs = data.ImageIndex[i].Transforms.Length; + data.ImageIndex[i].PinStates = Enumerable.Repeat(true, numXfs).ToArray(); + data.ImageIndex[i].TintStates = Enumerable.Repeat(true, numXfs).ToArray(); + data.ImageIndex[i].GroupIds = Enumerable.Repeat(0u, numXfs).ToArray(); + } + } + + // Default models to pinned, if they're local. Poly assets are unpinned. + if (data.ModelIndex != null) + { + for (int i = 0; i < data.ModelIndex.Length; ++i) + { + if (data.ModelIndex[i].PinStates == null) + { + int numXfs = (data.ModelIndex[i].Transforms != null) ? + data.ModelIndex[i].Transforms.Length : + data.ModelIndex[i].RawTransforms.Length; + data.ModelIndex[i].PinStates = new bool[numXfs]; + } + + for (int j = 0; j < data.ModelIndex[i].PinStates.Length; ++j) + { + data.ModelIndex[i].PinStates[j] = (data.ModelIndex[i].Location.GetLocationType() != + Model.Location.Type.IcosaAssetId); + } + } + } + + data.SchemaVersion = 1; + } + + // Append value to array, creating array if necessary + static T[] SafeAppend(T[] array, T value) + { + T[] asArray = { value }; + return (array == null) ? asArray : array.Concat(asArray).ToArray(); + } + + // SchemaVersion 2: M19 + // Converts data.ModelIndex[].InSet to data.ModelIndex[].RawTransforms[] + // This changes the behavior slightly: sets are immovable, but RawTransforms[] can be unpinned. + // This essentially removes the experimental Set feature. + static void UpgradeSchema_1to2(SketchMetadata data) + { + Debug.Assert(data.SchemaVersion == 1); + if (data.ModelIndex == null) { return; } + foreach (TiltModels75 tm75 in data.ModelIndex) + { + if (!tm75.InSet_deprecated) { continue; } + // Only one of Transforms[] or RawTransforms[] can be non-null. + // Therefore, we can only append to RawTransforms[] if Transforms[] is null. + if (tm75.Transforms != null) + { + Debug.LogError("Cannot upgrade InSet if Transforms[] is non-null"); + continue; + } + tm75.InSet_deprecated = false; + tm75.m_rawTransforms = SafeAppend(tm75.m_rawTransforms, TrTransform.identity); + tm75.PinStates = SafeAppend(tm75.PinStates, true); + } + data.SchemaVersion = 2; + } + } +} // namespace TiltBrush diff --git a/Assets/Scripts/Save/SaveLoadScript.cs b/Assets/Scripts/Save/SaveLoadScript.cs index 3b4525b418..38a06e0671 100644 --- a/Assets/Scripts/Save/SaveLoadScript.cs +++ b/Assets/Scripts/Save/SaveLoadScript.cs @@ -341,7 +341,7 @@ public IEnumerator SaveMonoscopic(int slot) /// we either preserve SourceId, or if this was a cloud sketch set it from the original asset. public string TransferredSourceIdFrom(SceneFileInfo info) { - if (info is PolySceneFileInfo polyInfo) + if (info is IcosaSceneFileInfo polyInfo) { // If the original is a Poly sketch it becomes the source. return polyInfo.AssetId; @@ -763,7 +763,7 @@ public bool Load(SceneFileInfo fileInfo, bool bAdditive = false) CustomColorPaletteStorage.m_Instance.SetColorsFromPalette(jsonData.Palette); // Images are not stored on Poly either. // TODO - will this assumption still hold with Icosa? - if (!(fileInfo is PolySceneFileInfo)) + if (!(fileInfo is IcosaSceneFileInfo)) { if (ReferenceImageCatalog.m_Instance != null && jsonData.ImageIndex != null) { diff --git a/Assets/Scripts/Save/SketchCatalog.cs b/Assets/Scripts/Save/SketchCatalog.cs index e813aeed74..cd995df4d2 100644 --- a/Assets/Scripts/Save/SketchCatalog.cs +++ b/Assets/Scripts/Save/SketchCatalog.cs @@ -1,123 +1,132 @@ -// Copyright 2020 The Tilt Brush Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// 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.IO; -using UnityEngine; - -namespace TiltBrush -{ - - public enum SketchSetType - { - User, - Curated, - Liked, - Drive, - } - - // SketchCatalog.Awake must come after App.Awake - public class SketchCatalog : MonoBehaviour - { - static public SketchCatalog m_Instance; - - // This folder contains json files which define where to pull the sketch thumbnail and data - // from Poly. These are used to populate the showcase when we can't query Poly. - // Obviously, if Poly as a database is deleted or moved, accessing these files will fail. - public const string kDefaultShowcaseSketchesFolder = "DefaultShowcaseSketches"; - - private SketchSet[] m_Sets; - - public SketchSet GetSet(SketchSetType eType) - { - return m_Sets[(int)eType]; - } - - void Awake() - { - m_Instance = this; - - if (Application.platform == RuntimePlatform.OSXEditor || - Application.platform == RuntimePlatform.OSXPlayer) - { - // force KEvents implementation of FileSystemWatcher - // source: https://github.com/mono/mono/blob/master/mcs/class/System/System.IO/FileSystemWatcher.cs - // Unity bug: https://fogbugz.unity3d.com/default.asp?778750_fncnl0np45at4mq1 - System.Environment.SetEnvironmentVariable("MONO_MANAGED_WATCHER", "3"); - } - - int maxTriangles = QualityControls.m_Instance.AppQualityLevels.MaxPolySketchTriangles; - - InitFeaturedSketchesPath(); - - m_Sets = new SketchSet[] - { - new FileSketchSet(), - new FileSketchSet(App.FeaturedSketchesPath()), - new PolySketchSet(this, SketchSetType.Liked, maxTriangles, needsLogin: true), - new GoogleDriveSketchSet(), - }; - } - - public static bool InitFeaturedSketchesPath() - { - string featuredPath = App.FeaturedSketchesPath(); - if (!App.InitDirectoryAtPath(featuredPath)) { return false; } - - TextAsset[] textAssets = - Resources.LoadAll(SketchCatalog.kDefaultShowcaseSketchesFolder); - foreach (var asset in textAssets) - { - if (asset.name.EndsWith(".tilt")) - { - string filePath = Path.Combine(App.FeaturedSketchesPath(), asset.name); - if (!File.Exists(filePath)) - { - File.WriteAllBytes(filePath, asset.bytes); - } - } - Resources.UnloadAsset(asset); - } - - return true; - } - - void Start() - { - foreach (SketchSet s in m_Sets) - { - s.Init(); - } - } - - void Update() - { - foreach (SketchSet s in m_Sets) - { - s.Update(); - } - } - - public void NotifyUserFileCreated(string fullpath) - { - m_Sets[(int)SketchSetType.User].NotifySketchCreated(fullpath); - } - - public void NotifyUserFileChanged(string fullpath) - { - m_Sets[(int)SketchSetType.User].NotifySketchChanged(fullpath); - } - } - - -} // namespace TiltBrush +// Copyright 2020 The Tilt Brush Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// 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.IO; +using UnityEngine; + +namespace TiltBrush +{ + + public enum SketchSetType + { + User, + Curated, + Liked, + Drive, + } + + // SketchCatalog.Awake must come after App.Awake + public class SketchCatalog : MonoBehaviour + { + static public SketchCatalog m_Instance; + + // This folder contains json files which define where to pull the sketch thumbnail and data + // from Poly. These are used to populate the showcase when we can't query Poly. + // Obviously, if Poly as a database is deleted or moved, accessing these files will fail. + public const string kDefaultShowcaseSketchesFolder = "DefaultShowcaseSketches"; + + private SketchSet[] m_Sets; + + public SketchSet GetSet(SketchSetType eType) + { + return m_Sets[(int)eType]; + } + + void Awake() + { + m_Instance = this; + + if (Application.platform == RuntimePlatform.OSXEditor || + Application.platform == RuntimePlatform.OSXPlayer) + { + // force KEvents implementation of FileSystemWatcher + // source: https://github.com/mono/mono/blob/master/mcs/class/System/System.IO/FileSystemWatcher.cs + // Unity bug: https://fogbugz.unity3d.com/default.asp?778750_fncnl0np45at4mq1 + System.Environment.SetEnvironmentVariable("MONO_MANAGED_WATCHER", "3"); + } + + int maxTriangles = QualityControls.m_Instance.AppQualityLevels.MaxPolySketchTriangles; + + SketchSet featuredSketchSet = null; + if (false) // TODO this fails because of initialization order: (VrAssetService.m_Instance.m_UseLocalFeaturedSketches) + { + featuredSketchSet = new FileSketchSet(App.FeaturedSketchesPath()); + InitFeaturedSketchesPath(); + } + else + { + featuredSketchSet = new IcosaSketchSet(this, SketchSetType.Curated, maxTriangles); + } + + m_Sets = new SketchSet[] + { + new FileSketchSet(), + featuredSketchSet, + new IcosaSketchSet(this, SketchSetType.Liked, maxTriangles, needsLogin: true), + new GoogleDriveSketchSet(), + }; + } + + public static bool InitFeaturedSketchesPath() + { + string featuredPath = App.FeaturedSketchesPath(); + if (!App.InitDirectoryAtPath(featuredPath)) { return false; } + + TextAsset[] textAssets = + Resources.LoadAll(SketchCatalog.kDefaultShowcaseSketchesFolder); + foreach (var asset in textAssets) + { + if (asset.name.EndsWith(".tilt")) + { + string filePath = Path.Combine(App.FeaturedSketchesPath(), asset.name); + if (!File.Exists(filePath)) + { + File.WriteAllBytes(filePath, asset.bytes); + } + } + Resources.UnloadAsset(asset); + } + + return true; + } + + void Start() + { + foreach (SketchSet s in m_Sets) + { + s.Init(); + } + } + + void Update() + { + foreach (SketchSet s in m_Sets) + { + s.Update(); + } + } + + public void NotifyUserFileCreated(string fullpath) + { + m_Sets[(int)SketchSetType.User].NotifySketchCreated(fullpath); + } + + public void NotifyUserFileChanged(string fullpath) + { + m_Sets[(int)SketchSetType.User].NotifySketchChanged(fullpath); + } + } + + +} // namespace TiltBrush diff --git a/Assets/Scripts/Save/SketchMetadata.cs b/Assets/Scripts/Save/SketchMetadata.cs index b20cfe80c3..f92d74eda5 100644 --- a/Assets/Scripts/Save/SketchMetadata.cs +++ b/Assets/Scripts/Save/SketchMetadata.cs @@ -1,820 +1,820 @@ -// Copyright 2020 The Tilt Brush Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// 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 Newtonsoft.Json; -using System; -using System.Linq; -using UnityEngine; - -namespace TiltBrush -{ - /* metadata.json format changes and additions - - - == v7.0: Single models introduced - - New list added called Models - This list could theoretically contain as many models as the user liked, but we cut it back. - In the wild, this list should only ever be of length zero or one, never null. - - "Models": [ - { - "FilePath": "C:\\Users\\Person\\Documents\\Tilt Brush\\Models\\Lili.obj", - "Position": [ -6.38644, 12.7471752, 8.778034 ], - "Rotation": [ 0.018738009, -0.861053467, -0.00643645832, -0.5081283 ], - "Scale": [ 0.649798400, 0.649798400, 0.649798400 ] - } - ] - - - == v7.5: Multiple models and images introduced - - ModelIndex replaces Models - ImageIndex added - These lists contained one entry for every unique object. Each entry in the list contained - a transform for each instance of the object in the sketch. - Both ModelIndex and ImageIndex can be null, and will never be zero length. - - "ImageIndex": [ - { - "FileName": "Blue And teal gradient.png", - "AspectRatio": 1.77777779, - "Transforms": [ [ [ 86.13458, 78.30929, 58.5603828 ], [ 0.0259972736, -0.291850924, -0.00451487023, -0.956099868 ], 198.431992 ] ] - } - ] - - "ModelIndex": [ - { - "FilePath": "Media Library\\Models\\3a. limbs 3\\5.obj", - "Transforms": [ [ [ -3.953864, 3.135213, -9.598504 ], [ 0.06734027, 0.287244231, -0.08482468, -0.9517147 ], 1.37809682 ] - ] - }, - ... - ] - - - == v7.5-experimental: Guides introduced - - Guides are saved as a list of all models, one tranform per instance. - Their shapes are saved as indices since we can guarantee consistency in those. - - "Guides": [ - { - "Type": 0, - "Transform": [ [ -3.60909033, 9.355544, -0.7895982 ], [ 0.161795944, 0.100251839, -0.007717509, 0.9816884 ], 2.0 ] - } - ] - - - == v7.5b: Guides updated. - - List turned into an index. - Type stored as a string. - Size stored as transform.scale + Custom. - - "GuideIndex": [ - { - "Type": "Capsule", - "States": [ - { - "Transform": [ [ 4.216275, 19.4874744, -0.2948996 ], [ 0.101220131, 0.190763831, -0.1001101, 0.971257746 ], 4 ], - "Custom": [ .5, 2, .5 ] - } - ] - } - ] - - - == v8: Guides updated - - Extents stored explicitly. - Transform.scale is always 0. - Backwards-compatibility for 7.5b guides (finally removed in v19) - Type accidentally written out in hashed format :-P - - "GuideIndex": [ - { - "Type": "pmhghhkcdmp", - "States": [ - { - "Transform": [ [ 4.216275, 19.4874744, -0.2948996 ], [ 0.101220131, 0.190763831, -0.1001101, 0.971257746 ], 0.0 ], - "Extents": [ 2.50599027, 9.098843, 2.50599027 ] - } - ] - }, - ] - - == v8.2: Prepare for fixing Guides.Type - - Guides.Type supports human-readable values, although hashed values are still written - - - == v9.0b: Added initial version of Palette - - "Palette": { - "Colors": [ - { - "r": 50, - "g": 50, - "b": 230, - "a": 255 - } - ] - } - - - == v9.0: Removed Palette from save file until 9.1 - - == v9.1: Changed Palette format to use alpha-less and more-compact color values - - "Palette": { "Entries": [ [ 50, 50, 230, 255 ] ] } - - The 9.0b-style "Colors" field is ignored. - The alpha value is preserved when serializing, but will always be 255. - The alpha value is forced to 255 when deserializing. - - - == v10.0: Added CustomLights and CustomEnvironment to save file - - "Environment": { - "GradientColors": [ [ 100, 100, 100, 255 ], [ 60, 64, 90, 255 ] - ], - "GradientSkew": [ 0.0, 0.0, 0.0, 1.0 ], - "FogColor": [ 31, 31, 78, 255 ], - "FogDensity": 0.00141058769, - "ReflectionIntensity": 0.3 - } - - "Lights": { - "Ambient": [ 173, 173, 173, 255 ], - "Shadow": { - "Orientation": [ 0.5, 0.0, 0.0, 0.8660254 ], - "Color": [ 32.0, 31.8180237, 3.81469727E-06, 1.0 ] - }, - "NoShadow": { - "Orientation": [ 0.883022249, -0.321393818, 0.116977736, 0.321393818 ], - "Color": [ 0.03125, 0.000550092547, 0.0, 1.0 ] - } - } - - The "GradientColors" field of Environment is null if the gradient has not been accessed. - Orientation of lights is stored in scene space. - Colors stored as integer RGB are guaranteed to be LDR. Those as floating point RGB may be HDR. - - "SourceId": "abcdefg" - - If this sketch is derived from a Poly asset then SourceId is the id of that original asset. - - - == v12.0: Added Set to save file - - The set of a sketch comprises of props (models) that have been brought in unscaled and have - the root pivot placed at the origin. - File paths are relative to the Models directory. - - "Set": [ - "Andy/Andy.obj", - "Tiltasaurus/Tiltasaurus.obj" - ] - - - == v13.0: Added AssetId to Models - - Models can be loaded via AssetId, a lookup value for assets stored in Poly. - FilePath and AssetId should never both be valid, but AssetId is preferred in that errant case. - - Transforms are maintained for backward compatability for models. They can be read in but are no - longer written out. RawTransforms replaces it, where the new translation represents the pivot of - the models as specified in the original file instead of the center of the mesh bounds, and the - new scale represents the multiplier on the size of the original mesh instead of the normalization. - - M13 was never actually released to the public. - - "ModelIndex": [ - { - "FilePath": null, - "AssetId": "bzolM7RH0n6", - "InSet": false, - "Transforms": null, - "RawTransforms": [ [ [ -3.953864, 3.135213, -9.598504 ], [ 0.06734027, 0.287244231, -0.08482468, -0.9517147 ], 1.37809682 ] - ] - }, - - If a sketch has been uploaded to Poly we store the asset id so that future uploads can update - the existing asset rather than creating a new one. - - Controls for adding a model to a set were hidden behind a flag in M12 and disabled in M14. - - == v14.2: Deprecate Set - - Models that are in the Set of the v12 metadata will be written out in ModelIndex with InSet = true. - - == v15.0: Added Version, PinStates for models, images, and guides, TintStates for images - - SchemaVersion = 1 - - TiltModels75: Added PinStates[] and TintStates[]. Each is a bool[] with the same length as Transforms[]. - Files with SchemaVersion < 1 are upgraded to have PinStates and TintStates (both set to true) - ... - "PinStates": [ - true, - true, - false - ], - "TintStates": [ - true, - true, - false - ], - "Transforms": [ [ [ 2.81081581, 5.47280025, 6.80550051 ], [ -0.0380054265, -0.219284073, 0.00313296262, -0.9749155 ], 2.41691542 ], - [ [ 3.466383, 5.71923733, 6.45537853 ], [ -0.0334184356, -0.237726957, 0.0122604668, -0.9706796 ], 0.800769 ], - [ [ 4.00411844, 5.71402025, 6.12121439 ], [ -0.03800745, -0.354895175, 0.00206097914, -0.9341309 ], 0.760676444 ] - ] - ... - - Guide.State: added bool Pinned. - Files with SchemaVersion < 1 are upgraded with Pinned = true. - - == v19.0: Remove Guides.State.Custom, TiltModels75.InSet - - Guides.State.Custom only existed in the 7.5b file format, and was never released to the public. - Should have been removed long ago! - - InSet is converted to a pinned model with identity transform. - - == v22.0: Reference videos added. (TiltVideo[] Videos) - Camera paths added. (CameraPathMetadata[] CameraPaths) - Added GroupIds for TiltModels75, Guides.State, TiltImage75, and TiltVideo. - - "CameraPaths": [ - { - "PathKnots": [ - { - "Xf": [ [ 2.81081581, 5.47280025, 6.80550051 ], [ -0.0380054265, -0.219284073, 0.00313296262, -0.9749155 ], 2.41691542 ], - "Speed": 2.81081581 - }, - { - ... - } - ], - "RotationKnots": [ - { - "Xf": [ [ 2.81081581, 5.47280025, 6.80550051 ], [ -0.0380054265, -0.219284073, 0.00313296262, -0.9749155 ], 2.41691542 ], - "KnotIndex": 0, - "KnotT": 0.2, - }, - { - ... - } - "SpeedKnots": [ - { - "Xf": [ [ 2.81081581, 5.47280025, 6.80550051 ], [ -0.0380054265, -0.219284073, 0.00313296262, -0.9749155 ], 2.41691542 ], - "KnotIndex": 0, - "KnotT": 0.2, - "Speed": 2.81081581 - }, - { - ... - } - ], - }, - { - ... - } - ], - - PathKnots, RotationKnots, and SpeedKnots may all have 0 elements. RotationKnots and SpeedKnots - will not have >0 elements if PathKnots has 0 elements. - */ - - - // From v7.0 - [Serializable] - public class TiltModels70 - { - /// Absolute path to model. Relative paths are not supported. - public string FilePath { get; set; } - public Vector3 Position { get; set; } - public Quaternion Rotation { get; set; } - public Vector3 Scale { get; set; } - - public TiltModels75 Upgrade() - { - string relativePath; - try - { - relativePath = WidgetManager.GetModelSubpath(FilePath); - } - catch (ArgumentException) - { - relativePath = null; - } - // I guess keep it around, so we don't lose information. - if (relativePath == null) - { - relativePath = FilePath; - } - - return new TiltModels75 - { - FilePath = relativePath, - PinStates = new[] { true }, - Transforms = new[] { TrTransform.TRS(Position, Rotation, Scale.x) } - }; - } - } - - // Use for v7.5 and on - // Missing models are normally preserved, with these exceptions: - // - lost if a pre-M13 .tilt is saved in M13+ - // - InSet models are lost if saved, at least through M18 (b/65633544) - [Serializable] - public class TiltModels75 - { - /// Relative path to model from Media Library. - /// e.g. Media Library/Models/subdirectory/model.obj - /// With 14.0 on, this is unused if AssetId is valid. - [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] - public string FilePath { get; set; } - - /// AssetId for Poly. - /// Added in 14.0, this is preferred over FilePath. - [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] - public string AssetId { get; set; } - - // True if showing the untransformed, non-interactable model. - // Added in M13 in 97e210f041e20b87c72c87bafb71d7d399d46c13. Never released to public. - // Turned into RawTransforms in M19. - [JsonProperty( - PropertyName = "InSet", // Used to be called InSet - DefaultValueHandling = DefaultValueHandling.Ignore // Don't write "false" values into the .tilt any more - )] - [System.ComponentModel.DefaultValue(false)] - public bool InSet_deprecated { get; set; } - - // True if model should be pinned on load. Added in M15. - [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] - public bool[] PinStates { get; set; } - - /// Prior to M13, never null or empty; but an empty array is allowed on read. - /// Post M13, always null. - [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] - public TrTransform[] Transforms { get; set; } - - [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] - public string[] Subtrees { get; set; } - - /// Prior to M13, always null. - /// Post M13, never null or empty; but an empty array is allowed on read. - [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] - public TrTransform[] RawTransforms - { - get { return m_rawTransforms; } - set { m_rawTransforms = MetadataUtils.Sanitize(value); } - } - // Only for use by MetadataUtils.cs - [JsonIgnore] - public TrTransform[] m_rawTransforms; - - /// used to bridge the gap between strict Tilt Brush and not-so-strict json - [JsonIgnore] - public Model.Location Location - { - get - { - if (AssetId != null) - { - return Model.Location.PolyAsset(AssetId, null); - } - else if (FilePath != null) - { - return Model.Location.File(FilePath); - } - else - { - return new Model.Location(); // invalid location - } - } - set - { - if (value.GetLocationType() == Model.Location.Type.LocalFile) - { - FilePath = value.RelativePath; - AssetId = null; - } - else if (value.GetLocationType() == Model.Location.Type.PolyAssetId) - { - FilePath = null; - AssetId = value.AssetId; - } - } - } - - // Group IDs for widgets. 0 for ungrouped items. Added in M22. - [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] - public uint[] GroupIds { get; set; } - - [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] - public int[] LayerIds { get; set; } - } - - [Serializable] - public class Guides - { - // In 8.x we mistakenly wrote out hashed names for these shapes. - const string kHashedCube = "ldeocipaedc"; - const string kHashedSphere = "jminadgooco"; - const string kHashedCapsule = "pmhghhkcdmp"; - - // Custom dimensions for non-uniformly scaled stencils - [Serializable] - public class State - { - public TrTransform Transform { get; set; } - public Vector3 Extents { get; set; } - // True if guide should be pinned on load. Added in M15. - public bool Pinned { get; set; } - // Group ID for widget. 0 for ungrouped items. Added in M22. - public uint GroupId { get; set; } - public int LayerId { get; set; } - } - - // This is the accessor used by Json.NET for reading/writing the "Type" field. - // The getter is used for writing; the setter for reading. - [JsonProperty(PropertyName = "Type")] - private string SerializedType - { - get - { - string ret = Type.ToString(); - if (!Char.IsUpper(ret[0])) - { - // Must be an obfuscated value, or a numeric value (ie, an int that doesn't map - // to a valid enum name), neither of which is expected. Die early rather than - // generate garbage output, so we can catch it in testing. - Debug.LogErrorFormat("Writing bad stencil value {0}", ret); - return "Cube"; - } - return ret; - } - - set - { - try - { - Type = (StencilType)Enum.Parse(typeof(StencilType), value, true); - } - catch (ArgumentException e) - { - // Support the 8.x names for these - switch (value) - { - case kHashedCube: - Type = StencilType.Cube; - break; - case kHashedSphere: - Type = StencilType.Sphere; - break; - case kHashedCapsule: - Type = StencilType.Capsule; - break; - default: - // TODO: log a user visible warning? - Debug.LogException(e); - Type = StencilType.Cube; - break; - } - } - } - } - - [JsonIgnore] - public StencilType Type = StencilType.Cube; - - public State[] States { get; set; } - } - - [Serializable] - public class Palette - { - // Protect Tilt Brush from getting bad alpha values from the user. - [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] - private Color32[] Entries - { - get { return Colors; } - set - { - if (value != null) - { - for (int i = 0; i < value.Length; ++i) - { - value[i].a = 255; - } - } - Colors = value; - } - } - - [JsonIgnore] - public Color32[] Colors { get; set; } - } - - [Serializable] - public class CustomLights - { - [Serializable] - public class DirectionalLight - { - public Quaternion Orientation { get; set; } - public Color Color { get; set; } - } - - public Color32 Ambient { get; set; } - public DirectionalLight Shadow { get; set; } - public DirectionalLight NoShadow { get; set; } - } - - [Serializable] - public class CustomEnvironment - { - [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] - public Color32[] GradientColors { get; set; } - public Quaternion GradientSkew { get; set; } - public Color32 FogColor { get; set; } - public float FogDensity { get; set; } - public float ReflectionIntensity { get; set; } - - public string Skybox { get; set; } - } - - [Serializable] - public class CameraPathPositionKnotMetadata - { - public TrTransform Xf; - public float TangentMagnitude; - } - - [Serializable] - public class CameraPathRotationKnotMetadata - { - public TrTransform Xf; - public float PathTValue; - } - - [Serializable] - public class CameraPathSpeedKnotMetadata - { - public TrTransform Xf; - public float PathTValue; - public float Speed; - } - - [Serializable] - public class CameraPathFovKnotMetadata - { - public TrTransform Xf; - public float PathTValue; - public float Fov; - } - - [Serializable] - public class CameraPathMetadata - { - [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] - public CameraPathPositionKnotMetadata[] PathKnots { get; set; } - public CameraPathRotationKnotMetadata[] RotationKnots { get; set; } - public CameraPathSpeedKnotMetadata[] SpeedKnots { get; set; } - public CameraPathFovKnotMetadata[] FovKnots { get; set; } - } - - [Serializable] - public class LayerMetadata - { - [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] - public string Name; - [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] - public bool Visible; - } - - // TODO: deprecate (7.5b-only) - // Left just to avoid breaking trusted testers' art - [Serializable] - public class TiltImages75b - { - /// Absolute path to image; any path ending in .png or .jpg will work though. - public string FilePath { get; set; } - public TrTransform Transform { get; set; } - /// width / height - public float AspectRatio { get; set; } - - public TiltImages75 Upgrade() - { - return new TiltImages75 - { - FileName = System.IO.Path.GetFileName(FilePath), - AspectRatio = AspectRatio, - PinStates = new[] { true }, - TintStates = new[] { true }, - Transforms = new[] { Transform }, - GroupIds = new[] { 0u } - }; - } - } - - [Serializable] - public class TiltLights - { - public Color? LightColor; - public float? Intensity; - public LightType PunctualLightType; - public float? Range; - public float? InnerConeAngle; - public float? OuterConeAngle; - - public bool Pinned; - public TrTransform Transform; - // Group ID for widget. 0 for ungrouped items. - public uint GroupId { get; set; } - public int LayerId { get; set; } - } - - [Serializable] - public class TiltImages75 - { - /// *.png or *.jpg, should have no path - public string FileName { get; set; } - /// FileName plus path relative to images directory - public string FilePath { get; set; } - /// width / height - public float AspectRatio { get; set; } - // True if image should be pinned on load. Added in M15. - public bool[] PinStates { get; set; } - // True if image should use legacy tinting. Added in M15. - public bool[] TintStates { get; set; } - [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] - public TrTransform[] Transforms { get; set; } - // Group IDs for widgets. 0 for ungrouped items. Added in M22. - [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] - public uint[] GroupIds { get; set; } - [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] - public int[] LayerIds { get; set; } - public bool[] TwoSidedFlags { get; set; } - } - - [Serializable] - public class Mirror - { - public TrTransform Transform { get; set; } - } - - [Serializable] - public class TiltVideo - { - public string FilePath { get; set; } // relative to Media Library folder - public float AspectRatio { get; set; } - public bool Pinned; - public TrTransform Transform; - public bool Paused { get; set; } - public float Time { get; set; } - public float Volume { get; set; } - // Group ID for widget. 0 for ungrouped items. - public uint GroupId { get; set; } - public int LayerId { get; set; } - public bool TwoSided { get; set; } - } - - [Serializable] - // Serializable protects data members obfuscator, but we need to also protect - // method names like ShouldSerializeXxx(...) that are used by Json.NET - [System.Reflection.Obfuscation(Exclude = true)] - public class SketchMetadata - { - static public int kSchemaVersion = 2; - - // Reference to environment GUID. - public string EnvironmentPreset; - // Reference to sketch audio GUID. - [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] - public string AudioPreset { get; set; } - [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] - public string[] Authors { get; set; } - public Guid[] BrushIndex { get; set; } - [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] - public string[] RequiredCapabilities { get; set; } - public TrTransform ThumbnailCameraTransformInRoomSpace = TrTransform.identity; - public TrTransform SceneTransformInRoomSpace = TrTransform.identity; - // Callback for JSON.net (name is magic and special) - public bool ShouldSerializeSceneTransformInRoomSpace() - { - return SceneTransformInRoomSpace != TrTransform.identity; - } - public TrTransform CanvasTransformInSceneSpace = TrTransform.identity; - // Callback for JSON.net (name is magic and special) - public bool ShouldSerializeCanvasTransformInSceneSpace() - { - return CanvasTransformInSceneSpace != TrTransform.identity; - } - - // This was the old name of ThumbnailCameraTransformInRoomSpace. - [Serializable] - public struct UnusedSketchTransform - { - public Vector3 position; - public Quaternion orientation; - } - // This is write-only to keep it from being serialized out - public UnusedSketchTransform ThumbnailCameraTransform - { - set - { - var xf = TrTransform.TR(value.position, value.orientation); - ThumbnailCameraTransformInRoomSpace = xf; - } - } - - [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] - public int SchemaVersion { get; set; } - - /// Deprecated - /// Only written in 7.0-7.2 - /// Only should ever contains a single model but will create multiples if they are in the list - /// Write-only so it gets serialized in but not serialized out. - /// Models and ModelIndex will never coexist in the same .tilt, so we can upgrade in place. - [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] - public TiltModels70[] Models - { - set - { - ModelIndex = value.Select(m70 => m70.Upgrade()).ToArray(); - } - } - - /// Added in 7.5 - [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] - public TiltModels75[] ModelIndex { get; set; } - - [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] - public TiltLights[] LightIndex { get; set; } - - // Added in 7.5b; never released to public. - // Write-only so it gets serialized in but not serialized out. - // Images and ImageIndex will never coexist in the same .tilt, so we can upgrade in place. - [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] - public TiltImages75b[] Images - { - set - { - ImageIndex = value.Select(i75b => i75b.Upgrade()).ToArray(); - } - } - - // Added in 7.5 - [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] - public TiltImages75[] ImageIndex { get; set; } - - [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] - public Mirror Mirror { get; set; } - [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] - public Guides[] GuideIndex { get; set; } - // Added in 9.1 - [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] - public Palette Palette { get; set; } - // Added in 10.0 - [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] - public CustomLights Lights { get; set; } - [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] - public CustomEnvironment Environment { get; set; } - [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] - public string SourceId { get; set; } - // Added in 12.0, deprecated in 13.0 - [JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "Set")] - public string[] Set_deprecated { get; set; } - // Added in 13.0 - [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] - public string AssetId { get; set; } - // Added in 22.0 - [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] - public TiltVideo[] Videos { get; set; } - [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] - public LayerMetadata[] Layers { get; set; } - [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] - public CameraPathMetadata[] CameraPaths { get; set; } - - // Added for 24.0b Open-source edition - [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] - public string ApplicationName { get; set; } - [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] - public string ApplicationVersion { get; set; } - } -} // namespace TiltBrush +// Copyright 2020 The Tilt Brush Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// 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 Newtonsoft.Json; +using System; +using System.Linq; +using UnityEngine; + +namespace TiltBrush +{ + /* metadata.json format changes and additions + + + == v7.0: Single models introduced + + New list added called Models + This list could theoretically contain as many models as the user liked, but we cut it back. + In the wild, this list should only ever be of length zero or one, never null. + + "Models": [ + { + "FilePath": "C:\\Users\\Person\\Documents\\Tilt Brush\\Models\\Lili.obj", + "Position": [ -6.38644, 12.7471752, 8.778034 ], + "Rotation": [ 0.018738009, -0.861053467, -0.00643645832, -0.5081283 ], + "Scale": [ 0.649798400, 0.649798400, 0.649798400 ] + } + ] + + + == v7.5: Multiple models and images introduced + + ModelIndex replaces Models + ImageIndex added + These lists contained one entry for every unique object. Each entry in the list contained + a transform for each instance of the object in the sketch. + Both ModelIndex and ImageIndex can be null, and will never be zero length. + + "ImageIndex": [ + { + "FileName": "Blue And teal gradient.png", + "AspectRatio": 1.77777779, + "Transforms": [ [ [ 86.13458, 78.30929, 58.5603828 ], [ 0.0259972736, -0.291850924, -0.00451487023, -0.956099868 ], 198.431992 ] ] + } + ] + + "ModelIndex": [ + { + "FilePath": "Media Library\\Models\\3a. limbs 3\\5.obj", + "Transforms": [ [ [ -3.953864, 3.135213, -9.598504 ], [ 0.06734027, 0.287244231, -0.08482468, -0.9517147 ], 1.37809682 ] + ] + }, + ... + ] + + + == v7.5-experimental: Guides introduced + + Guides are saved as a list of all models, one tranform per instance. + Their shapes are saved as indices since we can guarantee consistency in those. + + "Guides": [ + { + "Type": 0, + "Transform": [ [ -3.60909033, 9.355544, -0.7895982 ], [ 0.161795944, 0.100251839, -0.007717509, 0.9816884 ], 2.0 ] + } + ] + + + == v7.5b: Guides updated. + + List turned into an index. + Type stored as a string. + Size stored as transform.scale + Custom. + + "GuideIndex": [ + { + "Type": "Capsule", + "States": [ + { + "Transform": [ [ 4.216275, 19.4874744, -0.2948996 ], [ 0.101220131, 0.190763831, -0.1001101, 0.971257746 ], 4 ], + "Custom": [ .5, 2, .5 ] + } + ] + } + ] + + + == v8: Guides updated + + Extents stored explicitly. + Transform.scale is always 0. + Backwards-compatibility for 7.5b guides (finally removed in v19) + Type accidentally written out in hashed format :-P + + "GuideIndex": [ + { + "Type": "pmhghhkcdmp", + "States": [ + { + "Transform": [ [ 4.216275, 19.4874744, -0.2948996 ], [ 0.101220131, 0.190763831, -0.1001101, 0.971257746 ], 0.0 ], + "Extents": [ 2.50599027, 9.098843, 2.50599027 ] + } + ] + }, + ] + + == v8.2: Prepare for fixing Guides.Type + + Guides.Type supports human-readable values, although hashed values are still written + + + == v9.0b: Added initial version of Palette + + "Palette": { + "Colors": [ + { + "r": 50, + "g": 50, + "b": 230, + "a": 255 + } + ] + } + + + == v9.0: Removed Palette from save file until 9.1 + + == v9.1: Changed Palette format to use alpha-less and more-compact color values + + "Palette": { "Entries": [ [ 50, 50, 230, 255 ] ] } + + The 9.0b-style "Colors" field is ignored. + The alpha value is preserved when serializing, but will always be 255. + The alpha value is forced to 255 when deserializing. + + + == v10.0: Added CustomLights and CustomEnvironment to save file + + "Environment": { + "GradientColors": [ [ 100, 100, 100, 255 ], [ 60, 64, 90, 255 ] + ], + "GradientSkew": [ 0.0, 0.0, 0.0, 1.0 ], + "FogColor": [ 31, 31, 78, 255 ], + "FogDensity": 0.00141058769, + "ReflectionIntensity": 0.3 + } + + "Lights": { + "Ambient": [ 173, 173, 173, 255 ], + "Shadow": { + "Orientation": [ 0.5, 0.0, 0.0, 0.8660254 ], + "Color": [ 32.0, 31.8180237, 3.81469727E-06, 1.0 ] + }, + "NoShadow": { + "Orientation": [ 0.883022249, -0.321393818, 0.116977736, 0.321393818 ], + "Color": [ 0.03125, 0.000550092547, 0.0, 1.0 ] + } + } + + The "GradientColors" field of Environment is null if the gradient has not been accessed. + Orientation of lights is stored in scene space. + Colors stored as integer RGB are guaranteed to be LDR. Those as floating point RGB may be HDR. + + "SourceId": "abcdefg" + + If this sketch is derived from a Poly asset then SourceId is the id of that original asset. + + + == v12.0: Added Set to save file + + The set of a sketch comprises of props (models) that have been brought in unscaled and have + the root pivot placed at the origin. + File paths are relative to the Models directory. + + "Set": [ + "Andy/Andy.obj", + "Tiltasaurus/Tiltasaurus.obj" + ] + + + == v13.0: Added AssetId to Models + + Models can be loaded via AssetId, a lookup value for assets stored in Poly. + FilePath and AssetId should never both be valid, but AssetId is preferred in that errant case. + + Transforms are maintained for backward compatability for models. They can be read in but are no + longer written out. RawTransforms replaces it, where the new translation represents the pivot of + the models as specified in the original file instead of the center of the mesh bounds, and the + new scale represents the multiplier on the size of the original mesh instead of the normalization. + + M13 was never actually released to the public. + + "ModelIndex": [ + { + "FilePath": null, + "AssetId": "bzolM7RH0n6", + "InSet": false, + "Transforms": null, + "RawTransforms": [ [ [ -3.953864, 3.135213, -9.598504 ], [ 0.06734027, 0.287244231, -0.08482468, -0.9517147 ], 1.37809682 ] + ] + }, + + If a sketch has been uploaded to Poly we store the asset id so that future uploads can update + the existing asset rather than creating a new one. + + Controls for adding a model to a set were hidden behind a flag in M12 and disabled in M14. + + == v14.2: Deprecate Set + + Models that are in the Set of the v12 metadata will be written out in ModelIndex with InSet = true. + + == v15.0: Added Version, PinStates for models, images, and guides, TintStates for images + + SchemaVersion = 1 + + TiltModels75: Added PinStates[] and TintStates[]. Each is a bool[] with the same length as Transforms[]. + Files with SchemaVersion < 1 are upgraded to have PinStates and TintStates (both set to true) + ... + "PinStates": [ + true, + true, + false + ], + "TintStates": [ + true, + true, + false + ], + "Transforms": [ [ [ 2.81081581, 5.47280025, 6.80550051 ], [ -0.0380054265, -0.219284073, 0.00313296262, -0.9749155 ], 2.41691542 ], + [ [ 3.466383, 5.71923733, 6.45537853 ], [ -0.0334184356, -0.237726957, 0.0122604668, -0.9706796 ], 0.800769 ], + [ [ 4.00411844, 5.71402025, 6.12121439 ], [ -0.03800745, -0.354895175, 0.00206097914, -0.9341309 ], 0.760676444 ] + ] + ... + + Guide.State: added bool Pinned. + Files with SchemaVersion < 1 are upgraded with Pinned = true. + + == v19.0: Remove Guides.State.Custom, TiltModels75.InSet + + Guides.State.Custom only existed in the 7.5b file format, and was never released to the public. + Should have been removed long ago! + + InSet is converted to a pinned model with identity transform. + + == v22.0: Reference videos added. (TiltVideo[] Videos) + Camera paths added. (CameraPathMetadata[] CameraPaths) + Added GroupIds for TiltModels75, Guides.State, TiltImage75, and TiltVideo. + + "CameraPaths": [ + { + "PathKnots": [ + { + "Xf": [ [ 2.81081581, 5.47280025, 6.80550051 ], [ -0.0380054265, -0.219284073, 0.00313296262, -0.9749155 ], 2.41691542 ], + "Speed": 2.81081581 + }, + { + ... + } + ], + "RotationKnots": [ + { + "Xf": [ [ 2.81081581, 5.47280025, 6.80550051 ], [ -0.0380054265, -0.219284073, 0.00313296262, -0.9749155 ], 2.41691542 ], + "KnotIndex": 0, + "KnotT": 0.2, + }, + { + ... + } + "SpeedKnots": [ + { + "Xf": [ [ 2.81081581, 5.47280025, 6.80550051 ], [ -0.0380054265, -0.219284073, 0.00313296262, -0.9749155 ], 2.41691542 ], + "KnotIndex": 0, + "KnotT": 0.2, + "Speed": 2.81081581 + }, + { + ... + } + ], + }, + { + ... + } + ], + + PathKnots, RotationKnots, and SpeedKnots may all have 0 elements. RotationKnots and SpeedKnots + will not have >0 elements if PathKnots has 0 elements. + */ + + + // From v7.0 + [Serializable] + public class TiltModels70 + { + /// Absolute path to model. Relative paths are not supported. + public string FilePath { get; set; } + public Vector3 Position { get; set; } + public Quaternion Rotation { get; set; } + public Vector3 Scale { get; set; } + + public TiltModels75 Upgrade() + { + string relativePath; + try + { + relativePath = WidgetManager.GetModelSubpath(FilePath); + } + catch (ArgumentException) + { + relativePath = null; + } + // I guess keep it around, so we don't lose information. + if (relativePath == null) + { + relativePath = FilePath; + } + + return new TiltModels75 + { + FilePath = relativePath, + PinStates = new[] { true }, + Transforms = new[] { TrTransform.TRS(Position, Rotation, Scale.x) } + }; + } + } + + // Use for v7.5 and on + // Missing models are normally preserved, with these exceptions: + // - lost if a pre-M13 .tilt is saved in M13+ + // - InSet models are lost if saved, at least through M18 (b/65633544) + [Serializable] + public class TiltModels75 + { + /// Relative path to model from Media Library. + /// e.g. Media Library/Models/subdirectory/model.obj + /// With 14.0 on, this is unused if AssetId is valid. + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public string FilePath { get; set; } + + /// AssetId for Poly. + /// Added in 14.0, this is preferred over FilePath. + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public string AssetId { get; set; } + + // True if showing the untransformed, non-interactable model. + // Added in M13 in 97e210f041e20b87c72c87bafb71d7d399d46c13. Never released to public. + // Turned into RawTransforms in M19. + [JsonProperty( + PropertyName = "InSet", // Used to be called InSet + DefaultValueHandling = DefaultValueHandling.Ignore // Don't write "false" values into the .tilt any more + )] + [System.ComponentModel.DefaultValue(false)] + public bool InSet_deprecated { get; set; } + + // True if model should be pinned on load. Added in M15. + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public bool[] PinStates { get; set; } + + /// Prior to M13, never null or empty; but an empty array is allowed on read. + /// Post M13, always null. + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public TrTransform[] Transforms { get; set; } + + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public string[] Subtrees { get; set; } + + /// Prior to M13, always null. + /// Post M13, never null or empty; but an empty array is allowed on read. + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public TrTransform[] RawTransforms + { + get { return m_rawTransforms; } + set { m_rawTransforms = MetadataUtils.Sanitize(value); } + } + // Only for use by MetadataUtils.cs + [JsonIgnore] + public TrTransform[] m_rawTransforms; + + /// used to bridge the gap between strict Tilt Brush and not-so-strict json + [JsonIgnore] + public Model.Location Location + { + get + { + if (AssetId != null) + { + return Model.Location.IcosaAsset(AssetId, null); + } + else if (FilePath != null) + { + return Model.Location.File(FilePath); + } + else + { + return new Model.Location(); // invalid location + } + } + set + { + if (value.GetLocationType() == Model.Location.Type.LocalFile) + { + FilePath = value.RelativePath; + AssetId = null; + } + else if (value.GetLocationType() == Model.Location.Type.IcosaAssetId) + { + FilePath = null; + AssetId = value.AssetId; + } + } + } + + // Group IDs for widgets. 0 for ungrouped items. Added in M22. + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public uint[] GroupIds { get; set; } + + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public int[] LayerIds { get; set; } + } + + [Serializable] + public class Guides + { + // In 8.x we mistakenly wrote out hashed names for these shapes. + const string kHashedCube = "ldeocipaedc"; + const string kHashedSphere = "jminadgooco"; + const string kHashedCapsule = "pmhghhkcdmp"; + + // Custom dimensions for non-uniformly scaled stencils + [Serializable] + public class State + { + public TrTransform Transform { get; set; } + public Vector3 Extents { get; set; } + // True if guide should be pinned on load. Added in M15. + public bool Pinned { get; set; } + // Group ID for widget. 0 for ungrouped items. Added in M22. + public uint GroupId { get; set; } + public int LayerId { get; set; } + } + + // This is the accessor used by Json.NET for reading/writing the "Type" field. + // The getter is used for writing; the setter for reading. + [JsonProperty(PropertyName = "Type")] + private string SerializedType + { + get + { + string ret = Type.ToString(); + if (!Char.IsUpper(ret[0])) + { + // Must be an obfuscated value, or a numeric value (ie, an int that doesn't map + // to a valid enum name), neither of which is expected. Die early rather than + // generate garbage output, so we can catch it in testing. + Debug.LogErrorFormat("Writing bad stencil value {0}", ret); + return "Cube"; + } + return ret; + } + + set + { + try + { + Type = (StencilType)Enum.Parse(typeof(StencilType), value, true); + } + catch (ArgumentException e) + { + // Support the 8.x names for these + switch (value) + { + case kHashedCube: + Type = StencilType.Cube; + break; + case kHashedSphere: + Type = StencilType.Sphere; + break; + case kHashedCapsule: + Type = StencilType.Capsule; + break; + default: + // TODO: log a user visible warning? + Debug.LogException(e); + Type = StencilType.Cube; + break; + } + } + } + } + + [JsonIgnore] + public StencilType Type = StencilType.Cube; + + public State[] States { get; set; } + } + + [Serializable] + public class Palette + { + // Protect Tilt Brush from getting bad alpha values from the user. + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + private Color32[] Entries + { + get { return Colors; } + set + { + if (value != null) + { + for (int i = 0; i < value.Length; ++i) + { + value[i].a = 255; + } + } + Colors = value; + } + } + + [JsonIgnore] + public Color32[] Colors { get; set; } + } + + [Serializable] + public class CustomLights + { + [Serializable] + public class DirectionalLight + { + public Quaternion Orientation { get; set; } + public Color Color { get; set; } + } + + public Color32 Ambient { get; set; } + public DirectionalLight Shadow { get; set; } + public DirectionalLight NoShadow { get; set; } + } + + [Serializable] + public class CustomEnvironment + { + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public Color32[] GradientColors { get; set; } + public Quaternion GradientSkew { get; set; } + public Color32 FogColor { get; set; } + public float FogDensity { get; set; } + public float ReflectionIntensity { get; set; } + + public string Skybox { get; set; } + } + + [Serializable] + public class CameraPathPositionKnotMetadata + { + public TrTransform Xf; + public float TangentMagnitude; + } + + [Serializable] + public class CameraPathRotationKnotMetadata + { + public TrTransform Xf; + public float PathTValue; + } + + [Serializable] + public class CameraPathSpeedKnotMetadata + { + public TrTransform Xf; + public float PathTValue; + public float Speed; + } + + [Serializable] + public class CameraPathFovKnotMetadata + { + public TrTransform Xf; + public float PathTValue; + public float Fov; + } + + [Serializable] + public class CameraPathMetadata + { + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public CameraPathPositionKnotMetadata[] PathKnots { get; set; } + public CameraPathRotationKnotMetadata[] RotationKnots { get; set; } + public CameraPathSpeedKnotMetadata[] SpeedKnots { get; set; } + public CameraPathFovKnotMetadata[] FovKnots { get; set; } + } + + [Serializable] + public class LayerMetadata + { + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public string Name; + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public bool Visible; + } + + // TODO: deprecate (7.5b-only) + // Left just to avoid breaking trusted testers' art + [Serializable] + public class TiltImages75b + { + /// Absolute path to image; any path ending in .png or .jpg will work though. + public string FilePath { get; set; } + public TrTransform Transform { get; set; } + /// width / height + public float AspectRatio { get; set; } + + public TiltImages75 Upgrade() + { + return new TiltImages75 + { + FileName = System.IO.Path.GetFileName(FilePath), + AspectRatio = AspectRatio, + PinStates = new[] { true }, + TintStates = new[] { true }, + Transforms = new[] { Transform }, + GroupIds = new[] { 0u } + }; + } + } + + [Serializable] + public class TiltLights + { + public Color? LightColor; + public float? Intensity; + public LightType PunctualLightType; + public float? Range; + public float? InnerConeAngle; + public float? OuterConeAngle; + + public bool Pinned; + public TrTransform Transform; + // Group ID for widget. 0 for ungrouped items. + public uint GroupId { get; set; } + public int LayerId { get; set; } + } + + [Serializable] + public class TiltImages75 + { + /// *.png or *.jpg, should have no path + public string FileName { get; set; } + /// FileName plus path relative to images directory + public string FilePath { get; set; } + /// width / height + public float AspectRatio { get; set; } + // True if image should be pinned on load. Added in M15. + public bool[] PinStates { get; set; } + // True if image should use legacy tinting. Added in M15. + public bool[] TintStates { get; set; } + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public TrTransform[] Transforms { get; set; } + // Group IDs for widgets. 0 for ungrouped items. Added in M22. + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public uint[] GroupIds { get; set; } + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public int[] LayerIds { get; set; } + public bool[] TwoSidedFlags { get; set; } + } + + [Serializable] + public class Mirror + { + public TrTransform Transform { get; set; } + } + + [Serializable] + public class TiltVideo + { + public string FilePath { get; set; } // relative to Media Library folder + public float AspectRatio { get; set; } + public bool Pinned; + public TrTransform Transform; + public bool Paused { get; set; } + public float Time { get; set; } + public float Volume { get; set; } + // Group ID for widget. 0 for ungrouped items. + public uint GroupId { get; set; } + public int LayerId { get; set; } + public bool TwoSided { get; set; } + } + + [Serializable] + // Serializable protects data members obfuscator, but we need to also protect + // method names like ShouldSerializeXxx(...) that are used by Json.NET + [System.Reflection.Obfuscation(Exclude = true)] + public class SketchMetadata + { + static public int kSchemaVersion = 2; + + // Reference to environment GUID. + public string EnvironmentPreset; + // Reference to sketch audio GUID. + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public string AudioPreset { get; set; } + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public string[] Authors { get; set; } + public Guid[] BrushIndex { get; set; } + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public string[] RequiredCapabilities { get; set; } + public TrTransform ThumbnailCameraTransformInRoomSpace = TrTransform.identity; + public TrTransform SceneTransformInRoomSpace = TrTransform.identity; + // Callback for JSON.net (name is magic and special) + public bool ShouldSerializeSceneTransformInRoomSpace() + { + return SceneTransformInRoomSpace != TrTransform.identity; + } + public TrTransform CanvasTransformInSceneSpace = TrTransform.identity; + // Callback for JSON.net (name is magic and special) + public bool ShouldSerializeCanvasTransformInSceneSpace() + { + return CanvasTransformInSceneSpace != TrTransform.identity; + } + + // This was the old name of ThumbnailCameraTransformInRoomSpace. + [Serializable] + public struct UnusedSketchTransform + { + public Vector3 position; + public Quaternion orientation; + } + // This is write-only to keep it from being serialized out + public UnusedSketchTransform ThumbnailCameraTransform + { + set + { + var xf = TrTransform.TR(value.position, value.orientation); + ThumbnailCameraTransformInRoomSpace = xf; + } + } + + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public int SchemaVersion { get; set; } + + /// Deprecated + /// Only written in 7.0-7.2 + /// Only should ever contains a single model but will create multiples if they are in the list + /// Write-only so it gets serialized in but not serialized out. + /// Models and ModelIndex will never coexist in the same .tilt, so we can upgrade in place. + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public TiltModels70[] Models + { + set + { + ModelIndex = value.Select(m70 => m70.Upgrade()).ToArray(); + } + } + + /// Added in 7.5 + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public TiltModels75[] ModelIndex { get; set; } + + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public TiltLights[] LightIndex { get; set; } + + // Added in 7.5b; never released to public. + // Write-only so it gets serialized in but not serialized out. + // Images and ImageIndex will never coexist in the same .tilt, so we can upgrade in place. + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public TiltImages75b[] Images + { + set + { + ImageIndex = value.Select(i75b => i75b.Upgrade()).ToArray(); + } + } + + // Added in 7.5 + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public TiltImages75[] ImageIndex { get; set; } + + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public Mirror Mirror { get; set; } + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public Guides[] GuideIndex { get; set; } + // Added in 9.1 + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public Palette Palette { get; set; } + // Added in 10.0 + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public CustomLights Lights { get; set; } + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public CustomEnvironment Environment { get; set; } + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public string SourceId { get; set; } + // Added in 12.0, deprecated in 13.0 + [JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "Set")] + public string[] Set_deprecated { get; set; } + // Added in 13.0 + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public string AssetId { get; set; } + // Added in 22.0 + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public TiltVideo[] Videos { get; set; } + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public LayerMetadata[] Layers { get; set; } + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public CameraPathMetadata[] CameraPaths { get; set; } + + // Added for 24.0b Open-source edition + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public string ApplicationName { get; set; } + [JsonProperty(NullValueHandling = NullValueHandling.Ignore)] + public string ApplicationVersion { get; set; } + } +} // namespace TiltBrush diff --git a/Assets/Scripts/SecretsConfig.cs b/Assets/Scripts/SecretsConfig.cs index 6b494ceabf..b2757576e4 100644 --- a/Assets/Scripts/SecretsConfig.cs +++ b/Assets/Scripts/SecretsConfig.cs @@ -27,6 +27,7 @@ public enum Service OculusMobile = 3, Pimax = 4, PhotonFusion = 5, + Icosa = 6 } [Serializable] diff --git a/Assets/Scripts/Sharing/AssetGetter.cs b/Assets/Scripts/Sharing/AssetGetter.cs index b880d8e173..9594ff06e0 100644 --- a/Assets/Scripts/Sharing/AssetGetter.cs +++ b/Assets/Scripts/Sharing/AssetGetter.cs @@ -1,251 +1,242 @@ -// Copyright 2020 The Tilt Brush Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// 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 Newtonsoft.Json; -using Newtonsoft.Json.Serialization; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Text; -using Newtonsoft.Json.Linq; -using UnityEngine; -using UnityEngine.Networking; - -namespace TiltBrush -{ - - /// Class that assists in getting a PolyRawAsset from Poly. - public class AssetGetter - { - private bool m_Ready; - private string m_URI; - private PolyRawAsset m_Asset; - private JsonSerializer m_JsonSerializer; - - /// Converts a property from snake case to camel case. - public class SnakeToCamelPropertyNameContractResolver : DefaultContractResolver - { - - protected override JsonProperty CreateProperty(MemberInfo member, - MemberSerialization memberSerialization) - { - JsonProperty jsonProperty = base.CreateProperty(member, memberSerialization); - jsonProperty.PropertyName = SnakeToCamelCase(jsonProperty.PropertyName); - return jsonProperty; - } - - string SnakeToCamelCase(string s) - { - int index = s.IndexOf("_"); - while (index != -1) - { - string toHere = s.Substring(0, index); - string upper = s.Substring(index + 1, 1); - string theRest = s.Substring(index + 2); - - s = toHere + upper.ToUpper() + theRest; - index = s.IndexOf("_"); - } - return s; - } - } - - public bool IsCanceled - { - get; - set; - } - - public bool IsReady - { - get { return m_Ready; } - } - - public PolyRawAsset Asset - { - get { return m_Asset; } - } - - public string Reason { get; } - - public AssetGetter(string uri, string assetId, VrAssetFormat assetType, - string reason) - { - m_URI = uri; - m_Asset = new PolyRawAsset(assetId, assetType); - m_JsonSerializer = new JsonSerializer(); - m_JsonSerializer.ContractResolver = new SnakeToCamelPropertyNameContractResolver(); - Reason = reason; - } - - // Initiates the contact with Poly. - public IEnumerator GetAssetCoroutine() - { - - OAuth2Identity identity = null; - - if (!m_URI.StartsWith(VrAssetService.ApiHost)) - { - m_Asset.SetRootElement(UnityWebRequest.EscapeURL(m_URI), m_URI); - } - else - { - - identity = App.GoogleIdentity; - - if (string.IsNullOrEmpty(App.Config.GoogleSecrets?.ApiKey)) - { - IsCanceled = true; - yield break; - } - m_Ready = false; - - WebRequest initialRequest = new WebRequest(m_URI, App.GoogleIdentity, UnityWebRequest.kHttpVerbGET); - using (var cr = initialRequest.SendAsync().AsIeNull()) - { - while (!initialRequest.Done) - { - try - { - cr.MoveNext(); - } - catch (VrAssetServiceException e) - { - Debug.LogException(e); - IsCanceled = true; - yield break; - } - yield return cr.Current; - } - } - - // Deserialize request string in to an Asset class. - MemoryStream memStream = new MemoryStream(Encoding.UTF8.GetBytes(initialRequest.Result)); - using (var jsonReader = new JsonTextReader(new StreamReader(memStream))) - { - Future f = new Future(() => JObject.Parse(initialRequest.Result)); - JObject json; - while (!f.TryGetResult(out json)) { yield return null; } - - if (json.Count == 0) - { - Debug.LogErrorFormat("Failed to deserialize response for {0}", m_URI); - yield break; - } - - // Find the asset by looking through the format list for the specified type. - VrAssetFormat requestedType = m_Asset.DesiredType; - - while (true) - { - var format = json["formats"]?.FirstOrDefault(x => - x["formatType"]?.ToString() == requestedType.ToString()); - if (format != null) - { - string internalRootFilePath = format["root"]?["relativePath"].ToString(); - // If we successfully get a gltf2 format file, internally change the extension to - // "gltf2" so that the cache knows that it is a gltf2 file. - if (requestedType == VrAssetFormat.GLTF2) - { - internalRootFilePath = Path.ChangeExtension(internalRootFilePath, "gltf2"); - } - - // Get root element info. - m_Asset.SetRootElement( - internalRootFilePath, - format["root"]?["url"].ToString()); - - // Get all resource infos. There may be zero. - foreach (var r in format["resources"]) - { - string path = r["relativePath"].ToString(); - m_Asset.AddResourceElement(path, r["url"].ToString()); - - // The root element should be the only gltf file. - Debug.Assert(!path.EndsWith(".gltf") && !path.EndsWith(".gltf2"), - string.Format("Found extra gltf resource: {0}", path)); - } - break; - } - else - { - // We asked for an asset in a format that it doesn't have. - // In some cases, we should look for a different format as backup. - if (requestedType == VrAssetFormat.GLTF2) - { - requestedType = VrAssetFormat.GLTF; - } - else - { - // In other cases, we should fail and get out. - Debug.LogErrorFormat("Can't download {0} in {1} format.", m_Asset.Id, m_Asset.DesiredType); - yield break; - } - } - } - } - } - - // Download root asset. - var request = new WebRequest(m_Asset.RootDataURL, identity); - using (var cr = request.SendAsync().AsIeNull()) - { - while (!request.Done) - { - try - { - cr.MoveNext(); - } - catch (VrAssetServiceException e) - { - Debug.LogErrorFormat("Error downloading {0} at {1}\n{2}", - m_Asset.Id, m_Asset.RootDataURL, e); - yield break; - } - yield return cr.Current; - } - } - m_Asset.CopyBytesToRootElement(request.ResultBytes); - - // Download all resource assets. - foreach (var e in m_Asset.ResourceElements) - { - request = new WebRequest(e.dataURL, App.GoogleIdentity); - using (var cr = request.SendAsync().AsIeNull()) - { - while (!request.Done) - { - try - { - cr.MoveNext(); - } - catch (VrAssetServiceException ex) - { - Debug.LogErrorFormat("Error downloading {0} at {1}\n{2}", - m_Asset.Id, m_Asset.RootDataURL, ex); - e.assetBytes = null; - yield break; - } - yield return cr.Current; - } - } - e.assetBytes = request.ResultBytes; - } - - m_Ready = true; - } - } - -} // namespace TiltBrush +// Copyright 2020 The Tilt Brush Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// 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 Newtonsoft.Json; +using Newtonsoft.Json.Serialization; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; +using Newtonsoft.Json.Linq; +using UnityEngine; +using UnityEngine.Networking; + +namespace TiltBrush +{ + + /// Class that assists in getting a PolyRawAsset from Poly. + public class AssetGetter + { + private bool m_Ready; + private string m_URI; + private IcosaRawAsset m_Asset; + private JsonSerializer m_JsonSerializer; + + /// Converts a property from snake case to camel case. + public class SnakeToCamelPropertyNameContractResolver : DefaultContractResolver + { + + protected override JsonProperty CreateProperty(MemberInfo member, + MemberSerialization memberSerialization) + { + JsonProperty jsonProperty = base.CreateProperty(member, memberSerialization); + jsonProperty.PropertyName = SnakeToCamelCase(jsonProperty.PropertyName); + return jsonProperty; + } + + string SnakeToCamelCase(string s) + { + int index = s.IndexOf("_"); + while (index != -1) + { + string toHere = s.Substring(0, index); + string upper = s.Substring(index + 1, 1); + string theRest = s.Substring(index + 2); + + s = toHere + upper.ToUpper() + theRest; + index = s.IndexOf("_"); + } + return s; + } + } + + public bool IsCanceled + { + get; + set; + } + + public bool IsReady + { + get { return m_Ready; } + } + + public IcosaRawAsset Asset + { + get { return m_Asset; } + } + + public string Reason { get; } + + public AssetGetter(string uri, string assetId, VrAssetFormat assetType, + string reason) + { + m_URI = uri; + m_Asset = new IcosaRawAsset(assetId, assetType); + m_JsonSerializer = new JsonSerializer(); + m_JsonSerializer.ContractResolver = new SnakeToCamelPropertyNameContractResolver(); + Reason = reason; + } + + // Initiates the contact with Icosa + public IEnumerator GetAssetCoroutine() + { + + if (!m_URI.StartsWith(VrAssetService.m_Instance.IcosaApiRoot)) + { + m_Asset.SetRootElement(UnityWebRequest.EscapeURL(m_URI), m_URI); + } + else + { + m_Ready = false; + + WebRequest initialRequest = new WebRequest(m_URI); + using (var cr = initialRequest.SendAsync().AsIeNull()) + { + while (!initialRequest.Done) + { + try + { + cr.MoveNext(); + } + catch (VrAssetServiceException e) + { + Debug.LogException(e); + IsCanceled = true; + yield break; + } + yield return cr.Current; + } + } + + // Deserialize request string in to an Asset class. + MemoryStream memStream = new MemoryStream(Encoding.UTF8.GetBytes(initialRequest.Result)); + using (var jsonReader = new JsonTextReader(new StreamReader(memStream))) + { + Future f = new Future(() => JObject.Parse(initialRequest.Result)); + JObject json; + while (!f.TryGetResult(out json)) { yield return null; } + + if (json.Count == 0) + { + Debug.LogErrorFormat("Failed to deserialize response for {0}", m_URI); + yield break; + } + + // Find the asset by looking through the format list for the specified type. + VrAssetFormat requestedType = m_Asset.DesiredType; + + while (true) + { + var format = json["formats"]?.FirstOrDefault(x => + x["formatType"]?.ToString() == requestedType.ToString()); + if (format != null) + { + string internalRootFilePath = format["root"]?["relativePath"].ToString(); + // If we successfully get a gltf2 format file, internally change the extension to + // "gltf2" so that the cache knows that it is a gltf2 file. + if (requestedType == VrAssetFormat.GLTF2) + { + internalRootFilePath = Path.ChangeExtension(internalRootFilePath, "gltf2"); + } + + // Get root element info. + m_Asset.SetRootElement( + internalRootFilePath, + format["root"]?["url"].ToString()); + + // Get all resource infos. There may be zero. + foreach (var r in format["resources"]) + { + string path = r["relativePath"].ToString(); + m_Asset.AddResourceElement(path, r["url"].ToString()); + + // The root element should be the only gltf file. + Debug.Assert(!path.EndsWith(".gltf") && !path.EndsWith(".gltf2"), + string.Format("Found extra gltf resource: {0}", path)); + } + break; + } + else + { + // We asked for an asset in a format that it doesn't have. + // In some cases, we should look for a different format as backup. + if (requestedType == VrAssetFormat.GLTF2) + { + Debug.LogWarning($"No GLTF2 format found for {m_Asset.Id}. Trying GLTF1."); + requestedType = VrAssetFormat.GLTF; + } + else + { + // In other cases, we should fail and get out. + Debug.LogErrorFormat("Can't download {0} in {1} format.", m_Asset.Id, m_Asset.DesiredType); + yield break; + } + } + } + } + } + + // Download root asset. + var request = new WebRequest(m_Asset.RootDataURL); + using (var cr = request.SendAsync().AsIeNull()) + { + while (!request.Done) + { + try + { + cr.MoveNext(); + } + catch (VrAssetServiceException e) + { + Debug.LogErrorFormat("Error downloading {0} at {1}\n{2}", + m_Asset.Id, m_Asset.RootDataURL, e); + yield break; + } + yield return cr.Current; + } + } + m_Asset.CopyBytesToRootElement(request.ResultBytes); + + // Download all resource assets. + foreach (var e in m_Asset.ResourceElements) + { + request = new WebRequest(e.dataURL); + using (var cr = request.SendAsync().AsIeNull()) + { + while (!request.Done) + { + try + { + cr.MoveNext(); + } + catch (VrAssetServiceException ex) + { + Debug.LogErrorFormat("Error downloading {0} at {1}\n{2}", + m_Asset.Id, m_Asset.RootDataURL, ex); + e.assetBytes = null; + yield break; + } + yield return cr.Current; + } + } + e.assetBytes = request.ResultBytes; + } + + m_Ready = true; + } + } + +} // namespace TiltBrush diff --git a/Assets/Scripts/Sharing/AssetLister.cs b/Assets/Scripts/Sharing/AssetLister.cs index f742fd1278..7c8b1cf26a 100644 --- a/Assets/Scripts/Sharing/AssetLister.cs +++ b/Assets/Scripts/Sharing/AssetLister.cs @@ -1,159 +1,149 @@ -// Copyright 2020 The Tilt Brush Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// 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.Linq; -using Newtonsoft.Json.Linq; -using UnityEngine.Networking; - -namespace TiltBrush -{ - - /// Class that holds page state while calling Poly ListAssets. - public class AssetLister - { - private string m_Uri; - private string m_ErrorMessage; - private string m_PageToken; - - public bool HasMore { get { return m_PageToken != null; } } - - public AssetLister(string uri, string errorMessage) - { - m_Uri = uri; - m_ErrorMessage = errorMessage; - } - - public IEnumerator NextPage(List files) - { - string uri = m_PageToken == null ? m_Uri - : String.Format("{0}&page_token={1}", m_Uri, m_PageToken); - - WebRequest request = new WebRequest(uri, App.GoogleIdentity, UnityWebRequest.kHttpVerbGET); - using (var cr = request.SendAsync().AsIeNull()) - { - while (!request.Done) - { - try - { - cr.MoveNext(); - } - catch (VrAssetServiceException e) - { - e.UserFriendly = m_ErrorMessage; - throw; - } - yield return cr.Current; - } - } - - Future f = new Future(() => JObject.Parse(request.Result)); - JObject json; - while (!f.TryGetResult(out json)) { yield return null; } - - var assets = json["assets"]; - if (assets != null) - { - foreach (var asset in assets) - { - var info = new PolySceneFileInfo(asset); - info.Author = asset["displayName"].ToString(); - ; - files.Add(info); - } - } - JToken jPageToken = json["nextPageToken"]; - m_PageToken = jPageToken != null ? jPageToken.ToString() : null; - } - - public IEnumerator NextPage(List files, - string thumbnailSuffix) - { - string uri = m_PageToken == null ? m_Uri - : String.Format("{0}&page_token={1}", m_Uri, m_PageToken); - - WebRequest request = new WebRequest(uri, App.GoogleIdentity, UnityWebRequest.kHttpVerbGET); - using (var cr = request.SendAsync().AsIeNull()) - { - while (!request.Done) - { - try - { - cr.MoveNext(); - } - catch (VrAssetServiceException e) - { - e.UserFriendly = m_ErrorMessage; - throw; - } - yield return cr.Current; - } - } - Future f = new Future(() => JObject.Parse(request.Result)); - JObject json; - while (!f.TryGetResult(out json)) { yield return null; } - - if (json.Count == 0) { yield break; } - - JToken lastAsset = null; - var assets = json["assets"] ?? json["userAssets"]; - foreach (JToken possibleAsset in assets) - { - try - { - // User assets are nested in an 'asset' node. - JToken asset = possibleAsset["asset"] ?? possibleAsset; - if (asset["visibility"].ToString() == "PRIVATE") - { - continue; - } - - // We now don't filter the liked Poly objects, but we don't want to return liked Tilt Brush - // sketches so in this section we filter out anything with a Tilt file in it. - // Also, although currently all Poly objects have a GLTF representation we should probably - // not rely on that continuing, so we discard anything that doesn't have a GLTF (1) - // representation. We look for PGLTF and GLTF as for a lot of objects Poly is returning - // PGLTF without GLTF. - bool skipObject = false; - foreach (var format in asset["formats"]) - { - var formatType = format["formatType"].ToString(); - if (formatType == "TILT") - { - skipObject = true; - break; - } - } - if (skipObject) - { - continue; - } - lastAsset = asset; - string accountName = asset["authorName"]?.ToString() ?? "Unknown"; - files.Add(new PolyAssetCatalog.AssetDetails(asset, accountName, thumbnailSuffix)); - } - catch (NullReferenceException) - { - UnityEngine.Debug.LogErrorFormat("Failed to load asset: {0}", - lastAsset == null ? "NULL" : lastAsset.ToString()); - } - yield return null; - } - - JToken jPageToken = json["nextPageToken"]; - m_PageToken = jPageToken != null ? jPageToken.ToString() : null; - } - } -} // namespace TiltBrush +// Copyright 2020 The Tilt Brush Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// 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 Newtonsoft.Json.Linq; +using UnityEngine; +using UnityEngine.Networking; + +namespace TiltBrush +{ + + /// Class that holds page state while calling Poly ListAssets. + public class AssetLister + { + private string m_Uri; + private string m_ErrorMessage; + private string m_PageToken; + private int m_pageLimit = 10; + + public bool HasMore { get { return m_PageToken != null && Int16.Parse(m_PageToken) < m_pageLimit; } } + + public AssetLister(string uri, string errorMessage) + { + m_Uri = uri; + m_ErrorMessage = errorMessage; + } + + public IEnumerator NextPage(List files) + { + string uri = m_PageToken == null ? m_Uri : $"{m_Uri}&pageToken={m_PageToken}"; + + WebRequest request = new WebRequest(uri, App.Instance.IcosaToken); + using (var cr = request.SendAsync().AsIeNull()) + { + while (!request.Done) + { + try + { + cr.MoveNext(); + } + catch (VrAssetServiceException e) + { + e.UserFriendly = m_ErrorMessage; + throw; + } + yield return cr.Current; + } + } + + Future f = new Future(() => JObject.Parse(request.Result)); + JObject json; + while (!f.TryGetResult(out json)) { yield return null; } + + var assets = json["assets"]; + if (assets != null) + { + foreach (var asset in assets) + { + var info = new IcosaSceneFileInfo(asset); + info.Author = asset["authorName"].ToString(); + files.Add(info); + } + } + m_PageToken = json["nextPageToken"]?.ToString(); + } + + public IEnumerator NextPage(List files, + string thumbnailSuffix) + { + string uri = m_PageToken == null ? m_Uri : $"{m_Uri}&pageToken={m_PageToken}"; + + WebRequest request = new WebRequest(uri, App.Instance.IcosaToken); + using (var cr = request.SendAsync().AsIeNull()) + { + while (!request.Done) + { + try + { + cr.MoveNext(); + } + catch (VrAssetServiceException e) + { + e.UserFriendly = m_ErrorMessage; + throw; + } + yield return cr.Current; + } + } + Future f = new Future(() => JObject.Parse(request.Result)); + JObject json; + while (!f.TryGetResult(out json)) { yield return null; } + + if (json.Count == 0) { yield break; } + + JToken lastAsset = null; + var assets = json["assets"]; + foreach (JObject asset in assets) + { + try + { + if (asset["visibility"].ToString() == "PRIVATE") + { + continue; + } + + // We now don't filter the liked Icosa objects, but we don't want to return liked Tilt Brush + // sketches so in this section we filter out anything with a Tilt file in it. + bool skipObject = false; + foreach (var format in asset["formats"]) + { + var formatType = format["formatType"].ToString(); + if (formatType == "TILT") + { + skipObject = true; + break; + } + } + if (skipObject) + { + continue; + } + lastAsset = asset; + string accountName = asset["authorName"]?.ToString() ?? "Unknown"; + files.Add(new IcosaAssetCatalog.AssetDetails(asset, accountName, thumbnailSuffix)); + } + catch (NullReferenceException) + { + UnityEngine.Debug.LogErrorFormat("Failed to load asset: {0}", + lastAsset == null ? "NULL" : lastAsset.ToString()); + } + yield return null; + } + + m_PageToken = json["nextPageToken"]?.ToString(); + } + } +} // namespace TiltBrush diff --git a/Assets/Scripts/Sharing/GoogleDriveSketchSet.cs b/Assets/Scripts/Sharing/GoogleDriveSketchSet.cs index 520238f3a6..fd8db78ed4 100644 --- a/Assets/Scripts/Sharing/GoogleDriveSketchSet.cs +++ b/Assets/Scripts/Sharing/GoogleDriveSketchSet.cs @@ -1,441 +1,441 @@ -// Copyright 2020 The Tilt Brush Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// 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; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using UnityEngine; -using UnityEngine.Networking; -using DriveData = Google.Apis.Drive.v3.Data; -using static TiltBrush.DriveAccess; - -namespace TiltBrush -{ - /// A sketchset made up of the sketches stored on Google drive, excepting the ones that are copies - /// of the sketches on the local device. - public class GoogleDriveSketchSet : SketchSet - { - - public class GoogleDriveFileInfo : SceneFileInfo - { - private const string kCachePath = "DriveCache"; - private DriveData.File m_File; - private Texture2D m_Thumbnail; - private bool m_AbortLoad; - private string m_FileName; - private TiltFile m_TiltFile; - private FileStream m_DownloadStream; - private string m_SourceId; // If this is a derivative work of a poly asset, that asset id. - private string m_Source; - - public Texture2D Thumbnail => m_Thumbnail; - - public FileInfoType InfoType => FileInfoType.Cloud; - - public string HumanName => m_File?.Name ?? "Untitled"; - - public bool Valid => true; - - public bool Available => m_TiltFile != null; - - public string FullPath => Path.Combine(App.UserSketchPath(), HumanName); - - public bool Exists => true; - - public bool ReadOnly => true; - - public string AssetId => null; - - public string SourceId - { - get { return m_SourceId; } - set { m_SourceId = value; } - } - - public int? TriangleCount => null; - - public float Progress - { - get - { - if (m_DownloadStream == null) - { - return 1f; - } - return m_DownloadStream.Position / (float)m_File.Size.Value; - } - } - - public DateTime LastModifiedTime => m_File.ModifiedTime.Value; - - public string Source => m_Source; - - public string Description => m_File.Description; - - private string CachePath => Path.Combine(Application.temporaryCachePath, kCachePath); - - public GoogleDriveFileInfo(DriveData.File file, string source) - { - m_File = file; - m_FileName = Path.Combine(CachePath, m_File.Id + ".tilt"); - if (File.Exists(m_FileName)) - { - var fileInfo = new FileInfo(m_FileName); - if (DriveAccess.IsNewer(m_File, fileInfo)) - { - File.Delete(m_FileName); - } - else - { - m_TiltFile = new TiltFile(m_FileName); - } - } - - m_Source = source; - } - - public void Delete() - { - throw new NotImplementedException(); - } - - public string Rename(string newName) - { - throw new NotImplementedException(); - } - - public bool IsHeaderValid() - { - return true; // TODO - } - - public Stream GetReadStream(string subfileName) - { - return m_TiltFile.GetReadStream(subfileName); - } - - public IEnumerator LoadThumbnail() - { - UnityWebRequest request = UnityWebRequestTexture.GetTexture(m_File.ThumbnailLink, - nonReadable: true); - var operation = request.SendWebRequest(); - m_AbortLoad = false; - while (!operation.isDone && !m_AbortLoad) - { - yield return null; - } - if (m_AbortLoad) { yield break; } - if (!request.isNetworkError) - { - m_Thumbnail = DownloadHandlerTexture.GetContent(request); - } - // TODO: show broken texture url here? - } - - public void UnloadThumbnail() - { - m_AbortLoad = true; - UnityEngine.Object.Destroy(m_Thumbnail); - m_Thumbnail = null; - } - - public async Task DownloadAsync(CancellationToken token) - { - Directory.CreateDirectory(CachePath); - using (m_DownloadStream = new FileStream(m_FileName, FileMode.Create)) - { - try - { - await Retry(() => App.DriveAccess.DownloadFileAsync(m_File, m_DownloadStream, token)); - } - catch (OperationCanceledException) - { - m_DownloadStream.Close(); - File.Delete(m_FileName); - } - finally - { - m_DownloadStream = null; - } - } - File.SetLastWriteTime(m_FileName, m_File.ModifiedTime.Value); - m_TiltFile = new TiltFile(m_FileName); - } - } - - - private bool m_Refreshing; - private GoogleDriveFileInfo[] m_Sketches; - private Coroutine m_ThumbnailLoadingCoroutine; - private bool m_Changed; - - public SketchSetType Type => SketchSetType.Drive; - - public bool IsReadyForAccess => m_Sketches != null; - - public bool IsActivelyRefreshingSketches => m_Refreshing || App.DriveAccess.Initializing; - - public bool RequestedIconsAreLoaded => m_ThumbnailLoadingCoroutine == null; - - public int NumSketches => m_Sketches?.Length ?? 0; - - public void Init() - { - App.DriveAccess.OnReadyChanged += OnDriveEnabledChanged; - EnumerateTiltFilesWhenReady(); - } - - public bool IsSketchIndexValid(int iIndex) - { - return iIndex >= 0 && iIndex < NumSketches; - } - - public void RequestOnlyLoadedMetadata(List requests) - { - // Get rid of existing icons - for (int i = 0; i < NumSketches; ++i) - { - m_Sketches[i].UnloadThumbnail(); - } - Resources.UnloadUnusedAssets(); - - if (m_ThumbnailLoadingCoroutine != null) - { - App.Instance.StopCoroutine(m_ThumbnailLoadingCoroutine); - m_Refreshing = false; - } - - m_ThumbnailLoadingCoroutine = App.Instance.StartCoroutine(LoadThumbnailsCoroutine(requests)); - } - - public bool GetSketchIcon(int i, out Texture2D icon, out string[] authors, - out string description) - { - if (i < 0 || i >= NumSketches) - { - icon = null; - authors = null; - description = null; - return false; - } - var sketch = m_Sketches[i]; - icon = sketch.Thumbnail; - authors = new[] { $"From {sketch.Source}" }; - description = string.IsNullOrEmpty(sketch.Description) ? null : sketch.Description; - return icon != null; - } - - public SceneFileInfo GetSketchSceneFileInfo(int i) - { - if (i < 0 || i >= NumSketches) - { - return null; - } - return m_Sketches[i]; - } - - public string GetSketchName(int i) - { - return GetSketchSceneFileInfo(i)?.HumanName; - } - - public void DeleteSketch(int toDelete) - { - throw new NotImplementedException(); - } - - public void RenameSketch(int toRename, string newName) - { - throw new NotImplementedException(); - } - - public void PrecacheSketchModels(int i) - { - if (i >= 0 && i < NumSketches) - { - // TODO: this currently causes the models to also be loaded into memory - App.PolyAssetCatalog.PrecacheModels(m_Sketches[i], $"GoogleDriveSketchSet {i}"); - } - } - - public void NotifySketchCreated(string fullpath) - { - m_Changed = true; - } - - public void NotifySketchChanged(string fullpath) - { - m_Changed = true; - } - - public void RequestRefresh() - { - // nothing - } - - public void Update() - { - if (!App.GoogleIdentity.LoggedIn || !App.GoogleUserSettings.Initialized) - { - return; - } - if (!m_Refreshing && m_Changed) - { - m_Changed = false; - EnumerateTiltFilesAsync().AsAsyncVoid(); - } - } - - public event Action OnChanged; - - public event Action OnSketchRefreshingChanged; - - private void OnDriveEnabledChanged() - { - if (App.DriveSync.SyncEnabled) - { - EnumerateTiltFilesWhenReady(); - OnSketchRefreshingChanged?.Invoke(); - } - else - { - if (m_Sketches != null && m_Sketches.Length != 0) - { - foreach (var sketch in m_Sketches) - { - sketch.UnloadThumbnail(); - } - m_Sketches = null; - OnChanged?.Invoke(); - } - } - } - - /// This will enumerate tilt files if the Drive access is ready - but otherwise will add itself - /// the DriveAccess.OnReadyChanged event to get called when that happens. It removes itself from - /// the event afterwards. Multiple calls will only result in a single enumeration. - private void EnumerateTiltFilesWhenReady() - { - if (App.DriveAccess.Ready) - { - if (!m_Refreshing) - { - EnumerateTiltFilesAsync().AsAsyncVoid(); - } - App.DriveAccess.OnReadyChanged -= EnumerateTiltFilesWhenReady; - } - else - { - App.DriveAccess.OnReadyChanged += EnumerateTiltFilesWhenReady; - } - } - - private async Task EnumerateTiltFilesAsync() - { - m_Refreshing = true; - OnSketchRefreshingChanged?.Invoke(); - try - { - // Gets all the 'Sketches' folders within each device folder on Google Drive - List deviceFolders = - (await Retry(() => App.DriveAccess.GetFoldersInFolderAsync( - App.GoogleUserSettings.DriveSyncFolderId, CancellationToken.None))).ToList(); - - var sketchTasks = deviceFolders - .Select(x => EnumerateTiltFilesForDevice(x, CancellationToken.None)).ToArray(); - await Task.WhenAll(sketchTasks); - // If the sketch is a backup of something that came from the local machine, only show it if - // the file is no longer present on the local machine. - var sketchList = new List(); - for (int i = 0; i < deviceFolders.Count; ++i) - { - if (deviceFolders[i].Id == App.DriveAccess.DeviceFolder) - { - sketchList.AddRange(sketchTasks[i].Result.Where(x => !File.Exists(x.FullPath))); - } - else - { - sketchList.AddRange(sketchTasks[i].Result); - } - } - m_Sketches = sketchList.OrderByDescending(x => x.LastModifiedTime).ToArray(); - } - finally - { - await new WaitForUpdate(); - m_Refreshing = false; - OnSketchRefreshingChanged?.Invoke(); - OnChanged?.Invoke(); - } - } - - private async Task> EnumerateTiltFilesForDevice( - DriveData.File folder, CancellationToken token) - { - var sketchFolder = - await Retry(() => App.DriveAccess.GetFolderAsync("Sketches", folder.Id, token)); - if (sketchFolder == null) - { - return Enumerable.Empty(); - } - var files = await Retry(() => App.DriveAccess.GetFilesInFolderAsync(sketchFolder.Id, token)); - var tiltFiles = files.Where(x => Path.GetExtension(x.Name) == ".tilt"); - return tiltFiles.Select(x => new GoogleDriveFileInfo(x, folder.Name)); - } - - private IEnumerator LoadThumbnailsCoroutine(List requests) - { - if (requests.Count == 0) - { - yield break; - } - var loadingCoroutines = requests.Select(x => m_Sketches[x].LoadThumbnail()).ToArray(); - - // Stagger kicking off each loading coroutine by a frame - foreach (var coroutine in loadingCoroutines) - { - coroutine.MoveNext(); - yield return null; - } - - bool stillLoading; - do - { - stillLoading = false; - for (int i = 0; i < loadingCoroutines.Length; ++i) - { - var coroutine = loadingCoroutines[i]; - if (coroutine == null) - { - continue; - } - if (coroutine.MoveNext()) - { - stillLoading = true; - } - else - { - loadingCoroutines[i] = null; - } - } - yield return null; - } while (stillLoading); - m_ThumbnailLoadingCoroutine = null; - } - } -} // namespace TiltBrush +// Copyright 2020 The Tilt Brush Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// 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; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using UnityEngine; +using UnityEngine.Networking; +using DriveData = Google.Apis.Drive.v3.Data; +using static TiltBrush.DriveAccess; + +namespace TiltBrush +{ + /// A sketchset made up of the sketches stored on Google drive, excepting the ones that are copies + /// of the sketches on the local device. + public class GoogleDriveSketchSet : SketchSet + { + + public class GoogleDriveFileInfo : SceneFileInfo + { + private const string kCachePath = "DriveCache"; + private DriveData.File m_File; + private Texture2D m_Thumbnail; + private bool m_AbortLoad; + private string m_FileName; + private TiltFile m_TiltFile; + private FileStream m_DownloadStream; + private string m_SourceId; // If this is a derivative work of a poly asset, that asset id. + private string m_Source; + + public Texture2D Thumbnail => m_Thumbnail; + + public FileInfoType InfoType => FileInfoType.Cloud; + + public string HumanName => m_File?.Name ?? "Untitled"; + + public bool Valid => true; + + public bool Available => m_TiltFile != null; + + public string FullPath => Path.Combine(App.UserSketchPath(), HumanName); + + public bool Exists => true; + + public bool ReadOnly => true; + + public string AssetId => null; + + public string SourceId + { + get { return m_SourceId; } + set { m_SourceId = value; } + } + + public int? TriangleCount => null; + + public float Progress + { + get + { + if (m_DownloadStream == null) + { + return 1f; + } + return m_DownloadStream.Position / (float)m_File.Size.Value; + } + } + + public DateTime LastModifiedTime => m_File.ModifiedTime.Value; + + public string Source => m_Source; + + public string Description => m_File.Description; + + private string CachePath => Path.Combine(Application.temporaryCachePath, kCachePath); + + public GoogleDriveFileInfo(DriveData.File file, string source) + { + m_File = file; + m_FileName = Path.Combine(CachePath, m_File.Id + ".tilt"); + if (File.Exists(m_FileName)) + { + var fileInfo = new FileInfo(m_FileName); + if (DriveAccess.IsNewer(m_File, fileInfo)) + { + File.Delete(m_FileName); + } + else + { + m_TiltFile = new TiltFile(m_FileName); + } + } + + m_Source = source; + } + + public void Delete() + { + throw new NotImplementedException(); + } + + public string Rename(string newName) + { + throw new NotImplementedException(); + } + + public bool IsHeaderValid() + { + return true; // TODO + } + + public Stream GetReadStream(string subfileName) + { + return m_TiltFile.GetReadStream(subfileName); + } + + public IEnumerator LoadThumbnail() + { + UnityWebRequest request = UnityWebRequestTexture.GetTexture(m_File.ThumbnailLink, + nonReadable: true); + var operation = request.SendWebRequest(); + m_AbortLoad = false; + while (!operation.isDone && !m_AbortLoad) + { + yield return null; + } + if (m_AbortLoad) { yield break; } + if (!request.isNetworkError) + { + m_Thumbnail = DownloadHandlerTexture.GetContent(request); + } + // TODO: show broken texture url here? + } + + public void UnloadThumbnail() + { + m_AbortLoad = true; + UnityEngine.Object.Destroy(m_Thumbnail); + m_Thumbnail = null; + } + + public async Task DownloadAsync(CancellationToken token) + { + Directory.CreateDirectory(CachePath); + using (m_DownloadStream = new FileStream(m_FileName, FileMode.Create)) + { + try + { + await Retry(() => App.DriveAccess.DownloadFileAsync(m_File, m_DownloadStream, token)); + } + catch (OperationCanceledException) + { + m_DownloadStream.Close(); + File.Delete(m_FileName); + } + finally + { + m_DownloadStream = null; + } + } + File.SetLastWriteTime(m_FileName, m_File.ModifiedTime.Value); + m_TiltFile = new TiltFile(m_FileName); + } + } + + + private bool m_Refreshing; + private GoogleDriveFileInfo[] m_Sketches; + private Coroutine m_ThumbnailLoadingCoroutine; + private bool m_Changed; + + public SketchSetType Type => SketchSetType.Drive; + + public bool IsReadyForAccess => m_Sketches != null; + + public bool IsActivelyRefreshingSketches => m_Refreshing || App.DriveAccess.Initializing; + + public bool RequestedIconsAreLoaded => m_ThumbnailLoadingCoroutine == null; + + public int NumSketches => m_Sketches?.Length ?? 0; + + public void Init() + { + App.DriveAccess.OnReadyChanged += OnDriveEnabledChanged; + EnumerateTiltFilesWhenReady(); + } + + public bool IsSketchIndexValid(int iIndex) + { + return iIndex >= 0 && iIndex < NumSketches; + } + + public void RequestOnlyLoadedMetadata(List requests) + { + // Get rid of existing icons + for (int i = 0; i < NumSketches; ++i) + { + m_Sketches[i].UnloadThumbnail(); + } + Resources.UnloadUnusedAssets(); + + if (m_ThumbnailLoadingCoroutine != null) + { + App.Instance.StopCoroutine(m_ThumbnailLoadingCoroutine); + m_Refreshing = false; + } + + m_ThumbnailLoadingCoroutine = App.Instance.StartCoroutine(LoadThumbnailsCoroutine(requests)); + } + + public bool GetSketchIcon(int i, out Texture2D icon, out string[] authors, + out string description) + { + if (i < 0 || i >= NumSketches) + { + icon = null; + authors = null; + description = null; + return false; + } + var sketch = m_Sketches[i]; + icon = sketch.Thumbnail; + authors = new[] { $"From {sketch.Source}" }; + description = string.IsNullOrEmpty(sketch.Description) ? null : sketch.Description; + return icon != null; + } + + public SceneFileInfo GetSketchSceneFileInfo(int i) + { + if (i < 0 || i >= NumSketches) + { + return null; + } + return m_Sketches[i]; + } + + public string GetSketchName(int i) + { + return GetSketchSceneFileInfo(i)?.HumanName; + } + + public void DeleteSketch(int toDelete) + { + throw new NotImplementedException(); + } + + public void RenameSketch(int toRename, string newName) + { + throw new NotImplementedException(); + } + + public void PrecacheSketchModels(int i) + { + if (i >= 0 && i < NumSketches) + { + // TODO: this currently causes the models to also be loaded into memory + App.IcosaAssetCatalog.PrecacheModels(m_Sketches[i], $"GoogleDriveSketchSet {i}"); + } + } + + public void NotifySketchCreated(string fullpath) + { + m_Changed = true; + } + + public void NotifySketchChanged(string fullpath) + { + m_Changed = true; + } + + public void RequestRefresh() + { + // nothing + } + + public void Update() + { + if (!App.GoogleIdentity.LoggedIn || !App.GoogleUserSettings.Initialized) + { + return; + } + if (!m_Refreshing && m_Changed) + { + m_Changed = false; + EnumerateTiltFilesAsync().AsAsyncVoid(); + } + } + + public event Action OnChanged; + + public event Action OnSketchRefreshingChanged; + + private void OnDriveEnabledChanged() + { + if (App.DriveSync.SyncEnabled) + { + EnumerateTiltFilesWhenReady(); + OnSketchRefreshingChanged?.Invoke(); + } + else + { + if (m_Sketches != null && m_Sketches.Length != 0) + { + foreach (var sketch in m_Sketches) + { + sketch.UnloadThumbnail(); + } + m_Sketches = null; + OnChanged?.Invoke(); + } + } + } + + /// This will enumerate tilt files if the Drive access is ready - but otherwise will add itself + /// the DriveAccess.OnReadyChanged event to get called when that happens. It removes itself from + /// the event afterwards. Multiple calls will only result in a single enumeration. + private void EnumerateTiltFilesWhenReady() + { + if (App.DriveAccess.Ready) + { + if (!m_Refreshing) + { + EnumerateTiltFilesAsync().AsAsyncVoid(); + } + App.DriveAccess.OnReadyChanged -= EnumerateTiltFilesWhenReady; + } + else + { + App.DriveAccess.OnReadyChanged += EnumerateTiltFilesWhenReady; + } + } + + private async Task EnumerateTiltFilesAsync() + { + m_Refreshing = true; + OnSketchRefreshingChanged?.Invoke(); + try + { + // Gets all the 'Sketches' folders within each device folder on Google Drive + List deviceFolders = + (await Retry(() => App.DriveAccess.GetFoldersInFolderAsync( + App.GoogleUserSettings.DriveSyncFolderId, CancellationToken.None))).ToList(); + + var sketchTasks = deviceFolders + .Select(x => EnumerateTiltFilesForDevice(x, CancellationToken.None)).ToArray(); + await Task.WhenAll(sketchTasks); + // If the sketch is a backup of something that came from the local machine, only show it if + // the file is no longer present on the local machine. + var sketchList = new List(); + for (int i = 0; i < deviceFolders.Count; ++i) + { + if (deviceFolders[i].Id == App.DriveAccess.DeviceFolder) + { + sketchList.AddRange(sketchTasks[i].Result.Where(x => !File.Exists(x.FullPath))); + } + else + { + sketchList.AddRange(sketchTasks[i].Result); + } + } + m_Sketches = sketchList.OrderByDescending(x => x.LastModifiedTime).ToArray(); + } + finally + { + await new WaitForUpdate(); + m_Refreshing = false; + OnSketchRefreshingChanged?.Invoke(); + OnChanged?.Invoke(); + } + } + + private async Task> EnumerateTiltFilesForDevice( + DriveData.File folder, CancellationToken token) + { + var sketchFolder = + await Retry(() => App.DriveAccess.GetFolderAsync("Sketches", folder.Id, token)); + if (sketchFolder == null) + { + return Enumerable.Empty(); + } + var files = await Retry(() => App.DriveAccess.GetFilesInFolderAsync(sketchFolder.Id, token)); + var tiltFiles = files.Where(x => Path.GetExtension(x.Name) == ".tilt"); + return tiltFiles.Select(x => new GoogleDriveFileInfo(x, folder.Name)); + } + + private IEnumerator LoadThumbnailsCoroutine(List requests) + { + if (requests.Count == 0) + { + yield break; + } + var loadingCoroutines = requests.Select(x => m_Sketches[x].LoadThumbnail()).ToArray(); + + // Stagger kicking off each loading coroutine by a frame + foreach (var coroutine in loadingCoroutines) + { + coroutine.MoveNext(); + yield return null; + } + + bool stillLoading; + do + { + stillLoading = false; + for (int i = 0; i < loadingCoroutines.Length; ++i) + { + var coroutine = loadingCoroutines[i]; + if (coroutine == null) + { + continue; + } + if (coroutine.MoveNext()) + { + stillLoading = true; + } + else + { + loadingCoroutines[i] = null; + } + } + yield return null; + } while (stillLoading); + m_ThumbnailLoadingCoroutine = null; + } + } +} // namespace TiltBrush diff --git a/Assets/Scripts/Sharing/IcosaService.cs b/Assets/Scripts/Sharing/IcosaService.cs new file mode 100644 index 0000000000..3d76b76539 --- /dev/null +++ b/Assets/Scripts/Sharing/IcosaService.cs @@ -0,0 +1,245 @@ +// Copyright 2020 The Tilt Brush Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// 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.IO; +using System.Threading; +using System.Threading.Tasks; +using JetBrains.Annotations; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using UnityEngine; + +namespace TiltBrush +{ + class IcosaService + { + /// A paginated response, for use with GetNextPageAsync() + public interface Paginated + { + /// URI to the next page of results, or null + string NextUri { get; } + /// URI to the previous page of results, or null + string PreviousUri { get; } + } + + // Classes named "Related" seem to be shared between multiple different response types. + // My guess is "related" is meant in the database-join sense of the word, and each of + // these is its own table in the backend. + + // XxxRelated classes are listed here in alphabetical order. + // Classes specific to an API call are found right after the API wrapper. + // This violates conventions but is more convenient. + + [Serializable, UsedImplicitly] + public class AvatarRelated + { + [Serializable, UsedImplicitly] + public class inline_model + { + public string url; + public int width; + public int height; + public int size; + } + public inline_model[] images; + public string uri; + } + + [Serializable, UsedImplicitly] + public class TagRelated + { + public string slug; + public string uri; + } + + [Serializable, UsedImplicitly] + public class ThumbnailsRelated + { + [Serializable, UsedImplicitly] + public class inline_model_2 + { + public string url; + public int width; + public int size; + public string uid; + public int height; + } + public inline_model_2[] images; + } + + [Serializable, UsedImplicitly] + public class UserRelated + { + public string username; + public string profileUrl; + public string account; + public string displayName; + public string uid; + public AvatarRelated[] avatars; + public string uri; + } + + [Serializable, UsedImplicitly] + public class Options + { + public Dictionary background; + + public void SetBackgroundColor(Color color) + { + background = new Dictionary(); + background["color"] = "#" + ColorUtility.ToHtmlStringRGB(color); + } + } + + private readonly string m_accessToken; + + public IcosaService(string token) + { + m_accessToken = token; + } + + [Serializable, UsedImplicitly] + public class MeDetail + { + public string uid; + public string modelsUrl; + public int modelCount; + public string email; + public string website; + public string account; + public string displayName; + public string profileUrl; + public string uri; + public string username; + public AvatarRelated avatar; + public bool isLimited; + } + + [Serializable, UsedImplicitly] + public class ModelDetail + { + [Serializable, UsedImplicitly] + public class File + { + public int wireframeSize; + public int flag; + public string version; + public int modelSize; + public string uri; + public int osgjsSize; + public JObject metadata; + } + public JObject status; + public File[] files; + public string uid; + public TagRelated[] tags; + public string viewerUrl; + public string publishedAt; + public int likeCount; + public int commentCount; + public int vertexCount; + public UserRelated user; + public bool isDownloadable; + public string description; + public string name; + public JObject license; // license (object, optional), + public string editorUrl; + public string uri; + public int faceCount; + public ThumbnailsRelated thumbnails; + public JObject options; // options (object, optional) + } + + [Serializable, UsedImplicitly] + public class ModelDownload + { + [Serializable, UsedImplicitly] + public class inline_model_1 + { + public string url; // temporary URL where the archive can be downloaded + public int expires; // when the temporary URL will expire (in seconds) + } + // This is called "gltf" but it's actually just the .zip archive that was uploaded, I believe + public inline_model_1 gltf; + } + + // Documentation for this API is incorrect, so this was created by inspection of the result + // (and therefore may itself have errors) + [Serializable, UsedImplicitly] + public class xxModelLikesResponse : Paginated + { + [Serializable, UsedImplicitly] + public class ModelLikesList + { + public string uid; + public string viewerUrl; + public bool isProtected; + public int vertexCount; + public UserRelated user; + public bool isDownloadable; + public string description; + public string name; + public string uri; + public int faceCount; + public ThumbnailsRelated thumbnails; + } + public string previous; // uri + public string next; // uri + public ModelLikesList[] results; + + string Paginated.NextUri => next; + string Paginated.PreviousUri => previous; + } + + // TODO: /v3/search and /v3/me/search? + // The parameters to the search functions are the same, except /v3/me/search omits + // the "username" parameter, so maybe we can have a single function which wraps both. + + // + /// Pass: + /// temporaryDirectory - if passed, caller is responsible for cleaning it up + public async Task CreateModel( + string zipPath, IProgress progress, CancellationToken token, + Options options = null, string temporaryDirectory = null) + { + + // No compression because it's a compressed .zip already + WebRequest uploader = new WebRequest( + $"{VrAssetService.m_Instance.IcosaApiRoot}/assets", m_accessToken, "POST", compress: false); + + var moreParams = new List<(string, string)>(); + + // Not currently used or supported by the backend + if (options != null) + { + moreParams.Add(("options", JsonConvert.SerializeObject(options))); + } + + uploader.ProgressObject = progress; + WebRequest.Reply reply = await uploader.SendNamedDataAsync( + "files", File.OpenRead(zipPath), Path.GetFileName(zipPath), "application/zip", + moreParams: moreParams, token, temporaryDirectory); + return reply.Deserialize(); + } + + [Serializable, UsedImplicitly] + public struct CreateResponse + { + public string upload_job; + public string edit_url; + } + } +} // namespace TiltBrush diff --git a/Assets/Scripts/Sharing/IcosaService.cs.meta b/Assets/Scripts/Sharing/IcosaService.cs.meta new file mode 100644 index 0000000000..d785c9b77b --- /dev/null +++ b/Assets/Scripts/Sharing/IcosaService.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 3115bd38f5444bc395b95fb15d02dfe0 +timeCreated: 1698675823 \ No newline at end of file diff --git a/Assets/Scripts/Sharing/PolySketchSet.cs b/Assets/Scripts/Sharing/IcosaSketchSet.cs similarity index 86% rename from Assets/Scripts/Sharing/PolySketchSet.cs rename to Assets/Scripts/Sharing/IcosaSketchSet.cs index e13f13a06b..d28870d564 100644 --- a/Assets/Scripts/Sharing/PolySketchSet.cs +++ b/Assets/Scripts/Sharing/IcosaSketchSet.cs @@ -1,923 +1,919 @@ -// Copyright 2020 The Tilt Brush Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// 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 UnityEngine.Networking; -using System; -using System.Collections; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using Newtonsoft.Json.Linq; - -namespace TiltBrush -{ - - // TODO: Specify tag for which sketches to query (curated, liked etc.) - public class PolySketchSet : SketchSet - { - - const int kDownloadBufferSize = 1024 * 1024; // 1MB - - // Downloading is handled by PolySketchSet which will set the local paths - - private class PolySketch : Sketch - { - // This value holds the count of sketches that were downloaded by the sketch set - // before this one. It's used during our sort to retain order from Poly, while - // allowing a custom sort on top. - public int m_DownloadIndex; - private PolySceneFileInfo m_FileInfo; - private Texture2D m_Icon; - - public SceneFileInfo SceneFileInfo - { - get { return m_FileInfo; } - } - - public string[] Authors - { - get - { - return m_FileInfo.Author != null - ? new string[] { m_FileInfo.Author } - : new string[] { }; - } - } - - public Texture2D Icon - { - get { return m_Icon; } - set { m_Icon = value; } - } - - public bool IconAndMetadataValid - { - get { return m_Icon != null; } - } - - public PolySketch(PolySceneFileInfo info) - { - m_FileInfo = info; - } - - public void UnloadIcon() - { - UnityEngine.Object.Destroy(m_Icon); - m_Icon = null; - } - - // Not part of the interface - public PolySceneFileInfo PolySceneFileInfo - { - get { return m_FileInfo; } - } - } - - private const string kIntroSketchAssetId = "agqmaia62KE"; - private const int kIntroSketchIndex = 1; - - private List m_Sketches; - private Dictionary m_AssetIds; - private int m_TotalCount = 0; - private VrAssetService m_AssetService; - private MonoBehaviour m_Parent; - private bool m_Ready; - private bool m_RefreshRequested; - private bool m_NeedsLogin; - private bool m_LoggedIn; - private bool m_ActivelyRefreshingSketches; - private int m_MaximumSceneTriangles; - - private SketchSetType m_Type; - private string m_CacheDir; - private Coroutine m_RefreshCoroutine; - private float m_CooldownTimer; - private List m_RequestedIcons = new List(); - private Coroutine m_TextureLoaderCoroutine; - - public SketchSetType Type { get { return m_Type; } } - - public VrAssetService VrAssetService - { - set { m_AssetService = value; } - } - - public PolySketchSet(MonoBehaviour parent, SketchSetType type, int maxSceneTriangles, - bool needsLogin = false) - { - m_Parent = parent; - m_Sketches = new List(); - m_AssetIds = new Dictionary(); - m_Ready = false; - m_RefreshRequested = false; - m_Type = type; - m_NeedsLogin = needsLogin; - m_MaximumSceneTriangles = maxSceneTriangles; - } - - public void Init() - { - VrAssetService = VrAssetService.m_Instance; - m_LoggedIn = false; - m_RefreshRequested = true; - m_CooldownTimer = VrAssetService.m_Instance.m_SketchbookRefreshInterval; - } - - public bool IsReadyForAccess - { - get { return m_Ready; } - } - - public bool IsActivelyRefreshingSketches - { - get { return m_ActivelyRefreshingSketches; } - private set - { - m_ActivelyRefreshingSketches = value; - OnSketchRefreshingChanged(); - } - } - - public bool RequestedIconsAreLoaded - { - get { return false; } - } - - public int NumSketches - { - get { return m_TotalCount; } - } - - public void NotifySketchCreated(string fullpath) { } - - public void NotifySketchChanged(string fullpath) { } - - public void RequestRefresh() - { - m_RefreshRequested = true; - } - - public bool IsSketchIndexValid(int index) - { - return index >= 0 && index < m_TotalCount; - } - - public void RequestOnlyLoadedMetadata(List requests) - { - // Stop any current texture loading - if (m_TextureLoaderCoroutine != null) - { - m_Parent.StopCoroutine(m_TextureLoaderCoroutine); - m_TextureLoaderCoroutine = null; - } - // Nuke textures on all icons - foreach (var sketch in m_Sketches) - { - sketch.UnloadIcon(); - } - m_RequestedIcons.Clear(); - m_RequestedIcons.AddRange(requests); - m_TextureLoaderCoroutine = m_Parent.StartCoroutine(TextureLoaderCoroutine()); - } - - public bool GetSketchIcon(int iSketchIndex, out Texture2D icon, out string[] authors, - out string description) - { - description = null; - if (iSketchIndex >= m_Sketches.Count) - { - icon = null; - authors = null; - return false; - } - PolySketch sketch = m_Sketches[iSketchIndex]; - icon = sketch.Icon; - authors = sketch.Authors; - return icon != null; - } - - public SceneFileInfo GetSketchSceneFileInfo(int i) - { - return i < m_Sketches.Count ? m_Sketches[i].SceneFileInfo : null; - } - - public string GetSketchName(int i) - { - return i < m_Sketches.Count ? m_Sketches[i].SceneFileInfo.HumanName : null; - } - - public void RenameSketch(int toRename, string newName) - { - throw new NotImplementedException(); - } - - public void PrecacheSketchModels(int i) - { - if (i < m_Sketches.Count) - { - App.PolyAssetCatalog.PrecacheModels(m_Sketches[i].SceneFileInfo, $"PolySketchSet {i}"); - } - } - - public void DeleteSketch(int toDelete) - { - throw new NotImplementedException(); - } - - public void Update() - { - if (!VrAssetService.m_Instance.Available) - { - return; - } - - if (m_NeedsLogin) - { - bool loggedIn = App.GoogleIdentity.LoggedIn; - if (loggedIn != m_LoggedIn) - { - m_LoggedIn = loggedIn; - if (!loggedIn) - { - if (m_RefreshCoroutine != null) - { - m_Parent.StopCoroutine(m_RefreshCoroutine); - IsActivelyRefreshingSketches = false; - m_RefreshCoroutine = null; - m_Sketches.Clear(); - m_AssetIds.Clear(); - m_TotalCount = 0; - m_CacheDir = null; - OnChanged(); - } - } - else - { - // Lie about refreshing. The refresh coroutine will happen in time, but - // for the user, we want them to know something will happen [soon]. - IsActivelyRefreshingSketches = true; - m_RefreshCoroutine = m_Parent.StartCoroutine(PeriodicRefreshCoroutine()); - } - } - } - else if (m_RefreshRequested && m_RefreshCoroutine == null) - { - m_RefreshCoroutine = m_Parent.StartCoroutine(PeriodicRefreshCoroutine()); - } - } - - public event Action OnChanged = delegate { }; - - public event Action OnSketchRefreshingChanged = delegate { }; - - private IEnumerator PeriodicRefreshCoroutine() - { - while (true) - { - if (m_RefreshRequested) - { - yield return Refresh(); - m_RefreshRequested = false; - - // Don't poll the showcase - if (Type == SketchSetType.Curated) - { - yield break; - } - m_CooldownTimer = VrAssetService.m_Instance.m_SketchbookRefreshInterval; - } - else - { - yield return null; - } - while (m_CooldownTimer > 0.0f) - { - m_CooldownTimer -= Time.deltaTime; - yield return null; - } - } - } - - // Update our state from the cloud. - // There are three stages to this, each with a separate coroutine: - // 1: Pull all the metadata from the server and populate m_Sketches - // If there are changes: - // 2: Download any thumbnails and tilt files we don't already have - // 3: Clean up any cached files that are no longer referenced - private IEnumerator Refresh() - { - if (m_NeedsLogin && !m_LoggedIn) - { - m_Sketches.Clear(); - m_AssetIds.Clear(); - m_TotalCount = 0; - m_CacheDir = null; - OnChanged(); - yield break; - } - - if (m_CacheDir == null) - { - m_CacheDir = CacheDir(Type); - try - { - Directory.CreateDirectory(m_CacheDir); - } - catch (Exception ex) - { - // Most of the system exceptions returned by CreateDirectory are just things the user needs - // to fix, and may well be sorted by reinstalling. If it's an ArgumentNullExeption or not a - // SystemException, we need to know about it, so log the exception. - if (!(ex is SystemException) || ex is ArgumentNullException) - { - Debug.LogException(ex); - } - ControllerConsoleScript.m_Instance.AddNewLine( - $"Error creating cache directory. Try restarting {App.kAppDisplayName}.\n" + - $"If this error persists, try reinstalling {App.kAppDisplayName}.", true); - yield break; - } - } - - // While we're fetching metadata, hold a flag so we can message state in the UI. - IsActivelyRefreshingSketches = true; - yield return PopulateSketchesCoroutine(); - IsActivelyRefreshingSketches = false; - } - - // Fetch asset metadata from server and populate m_Sketches - private IEnumerator PopulateSketchesCoroutine() - { - // Replacement data structures that will be populated with incoming data. These - // temporary structures will be copied to the "live" structures in chunks, so - // beware of modifications that may reference incomplete data. - List sketches = new List(); - Dictionary assetIds = new Dictionary(); - - bool fromEmpty = m_AssetIds.Count == 0; - int loadSketchCount = 0; - - AssetLister lister = null; - List infos = new List(); - - // If we don't have a connection to Poly and we're querying the Showcase, use - // the json metadatas stored in resources, instead of trying to get them from Poly. - if (VrAssetService.m_Instance.NoConnection && m_Type == SketchSetType.Curated) - { - TextAsset[] textAssets = - Resources.LoadAll(SketchCatalog.kDefaultShowcaseSketchesFolder); - for (int i = 0; i < textAssets.Length; ++i) - { - JObject jo = JObject.Parse(textAssets[i].text); - infos.Add(new PolySceneFileInfo(jo)); - } - } - else - { - lister = m_AssetService.ListAssets(Type); - } - - bool changed = false; - int pagesFetched = 0; - while (lister == null || lister.HasMore || assetIds.Count == 0) - { - if (sketches.Count >= 180) - { - break; // Don't allow the sketchbook to become too big. - } - - // lister will be null if we can't connect to Poly and we've pre-populated infos - // with data from Resources. - if (lister != null) - { - using (var cr = lister.NextPage(infos)) - { - while (true) - { - try - { - if (!cr.MoveNext()) - { - break; - } - } - catch (VrAssetServiceException e) - { - ControllerConsoleScript.m_Instance.AddNewLine(e.UserFriendly); - Debug.LogException(e); - yield break; - } - yield return cr.Current; - } - } - } - if (infos.Count == 0) - { - break; - } - if (m_CacheDir == null) - { - yield break; - } - // Only cull the curated sketches. If a user likes a sketch that's very high poly count, - // there's no feedback to tell them why it didn't show up in their list. b/123649719 - if (m_Type == SketchSetType.Curated) - { - infos = infos.Where(x => x.GltfTriangleCount < m_MaximumSceneTriangles).ToList(); - } - if (m_Type == SketchSetType.Curated && !assetIds.Keys.Contains(kIntroSketchAssetId)) - { - yield return VrAssetService.m_Instance.InsertSketchInfo( - kIntroSketchAssetId, kIntroSketchIndex, infos); - } - for (int i = 0; i < infos.Count; i++) - { - PolySceneFileInfo info = infos[i]; - PolySketch sketch; - if (m_AssetIds.TryGetValue(info.AssetId, out sketch)) - { - // We already have this sketch - } - else - { - sketch = new PolySketch(info); - sketch.m_DownloadIndex = loadSketchCount++; - // Set local paths - info.TiltPath = Path.Combine(m_CacheDir, String.Format("{0}.tilt", info.AssetId)); - info.IconPath = Path.Combine(m_CacheDir, String.Format("{0}.png", info.AssetId)); - changed = true; - } - if (assetIds.ContainsKey(info.AssetId)) - { - Debug.LogErrorFormat("VR Asset Service has returned two objects with asset id '{0}'.", - info.AssetId); - } - else - { - sketches.Add(sketch); - assetIds.Add(info.AssetId, sketch); - } - } - infos.Clear(); - - // Only download the files with every other page, otherwise the sketch pages change too often, - // Which results in a bad user experience. - if ((++pagesFetched & 1) == 0 || lister == null || !lister.HasMore) - { - if (Type == SketchSetType.Curated) - { - sketches.Sort(CompareSketchesByTriangleCountAndDownloadIndex); - } - - // If populating the set from new then show stuff as it comes in. - // (We don't have to worry about anything being removed) - if (fromEmpty) - { - yield return DownloadFilesCoroutine(sketches); - RemoveFailedDownloads(sketches); - // Copying sketches to m_Sketches before sketches has completed populating is a bit - // dangerous, but as long as they're copied and then listeners are notified - // immediately afterward with OnChanged(), there data should be stable. - m_TotalCount = sketches.Count; - m_Sketches = new List(sketches); - m_AssetIds = assetIds; - m_Ready = true; - OnChanged(); - } - } - } - - if (!fromEmpty) - { - // Find anything that was removed - int removed = m_Sketches.Count(s => !assetIds.ContainsKey(s.PolySceneFileInfo.AssetId)); - if (removed > 0) - { - changed = true; - } - - // Download new files before we notify our listeners that we've got new stuff for them. - if (changed) - { - yield return DownloadFilesCoroutine(sketches); - RemoveFailedDownloads(sketches); - } - - // DeleteOldSketchesCoroutine relies on m_AssetIds being up to date, so set these before - // we try to cull the herd. - m_AssetIds = assetIds; - if (changed) - { - yield return DeleteOldSketchesCoroutine(); - } - - // Set new data live - m_TotalCount = sketches.Count; - m_Sketches = new List(sketches); - m_Ready = true; - if (changed) - { - OnChanged(); - } - } - else - { - // On first run populate, take the time to clean out any cobwebs. - // Note that this is particularly important for the curated sketches, which do not have - // a periodic refresh, meaning old sketches will never been deleted in the other path. - yield return DeleteOldSketchesCoroutine(); - OnChanged(); - } - } - - // If we have not managed to download a tilt file or its icon, we should remove it from the - // sketches list so as not to confuse the user. - private void RemoveFailedDownloads(List sketches) - { - sketches.RemoveAll(x => !x.PolySceneFileInfo.TiltDownloaded || - !x.PolySceneFileInfo.IconDownloaded); - } - - // Download tilt files and thumbnails (that we don't already have) - private IEnumerator DownloadFilesCoroutine(List sketches) - { - bool notifyOnError = true; - void NotifyCreateError(PolySceneFileInfo sceneFileInfo, string type, Exception ex) - { - string error = $"Error downloading {type} file for {sceneFileInfo.HumanName}."; - ControllerConsoleScript.m_Instance.AddNewLine(error, notifyOnError); - notifyOnError = false; - Debug.LogException(ex); - Debug.LogError($"{sceneFileInfo.HumanName} {sceneFileInfo.TiltPath}"); - } - - void NotifyWriteError(PolySceneFileInfo sceneFileInfo, string type, UnityWebRequest www) - { - string error = $"Error downloading {type} file for {sceneFileInfo.HumanName}.\n" + - "Out of disk space?"; - ControllerConsoleScript.m_Instance.AddNewLine(error, notifyOnError); - notifyOnError = false; - Debug.LogError($"{www.error} {sceneFileInfo.HumanName} {sceneFileInfo.TiltPath}"); - } - - byte[] downloadBuffer = new byte[kDownloadBufferSize]; - // Load the icons first, then the thumbnails - foreach (PolySketch sketch in sketches) - { - PolySceneFileInfo sceneFileInfo = sketch.PolySceneFileInfo; - // TODO(b/36270116): Check filesizes when Poly can give it to us to detect incomplete downloads - if (!sceneFileInfo.IconDownloaded) - { - if (File.Exists(sceneFileInfo.IconPath)) - { - sceneFileInfo.IconDownloaded = true; - } - else - { - using (UnityWebRequest www = UnityWebRequest.Get(sceneFileInfo.IconUrl)) - { - DownloadHandlerFastFile downloadHandler; - try - { - downloadHandler = new DownloadHandlerFastFile(sceneFileInfo.IconPath, downloadBuffer); - } - catch (Exception ex) - { - NotifyCreateError(sceneFileInfo, "icon", ex); - continue; - } - www.downloadHandler = downloadHandler; - yield return www.SendWebRequest(); - if (www.isNetworkError || www.responseCode >= 400 || !string.IsNullOrEmpty(www.error)) - { - NotifyWriteError(sceneFileInfo, "icon", www); - } - else - { - sceneFileInfo.IconDownloaded = true; - } - } - } - } - yield return null; - } - - foreach (PolySketch sketch in sketches) - { - PolySceneFileInfo sceneFileInfo = sketch.PolySceneFileInfo; - if (!sceneFileInfo.TiltDownloaded) - { - if (File.Exists(sceneFileInfo.TiltPath)) - { - sceneFileInfo.TiltDownloaded = true; - } - else - { - using (UnityWebRequest www = UnityWebRequest.Get(sceneFileInfo.TiltFileUrl)) - { - DownloadHandlerFastFile downloadHandler; - try - { - downloadHandler = new DownloadHandlerFastFile(sceneFileInfo.TiltPath, downloadBuffer); - } - catch (Exception ex) - { - NotifyCreateError(sceneFileInfo, "sketch", ex); - continue; - } - www.downloadHandler = downloadHandler; - yield return www.SendWebRequest(); - if (www.isNetworkError || www.responseCode >= 400 || !string.IsNullOrEmpty(www.error)) - { - NotifyWriteError(sceneFileInfo, "sketch", www); - } - else - { - sceneFileInfo.TiltDownloaded = true; - } - } - } - } - yield return null; - } - yield return null; - } - - // Delete any files that aren't referenced in m_Sketches (actually m_AssetIds) - // Does this on a background thread so prevent hitches. - private IEnumerator DeleteOldSketchesCoroutine() - { - if (m_CacheDir != null) - { - var task = new Future(() => - { - var unknown = new DirectoryInfo(m_CacheDir).GetFiles().Where( - f => !m_AssetIds.ContainsKey(Path.GetFileNameWithoutExtension(f.Name))); - foreach (var f in unknown) - { - f.Delete(); - } - return true; - }); - - bool unused; - while (!task.TryGetResult(out unused)) - { - yield return null; - } - } - } - - // Read the icon textures for all sketches in m_RequestedIcons - private IEnumerator TextureLoaderCoroutine() - { - while (m_RequestedIcons.Count > 0) - { - foreach (int i in m_RequestedIcons) - { - PolySketch sketch = m_Sketches[i]; - string path = sketch.PolySceneFileInfo.IconPath; - if (sketch.PolySceneFileInfo.IconDownloaded) - { - byte[] data = File.ReadAllBytes(path); - Texture2D t = new Texture2D(2, 2); - t.LoadImage(data); - sketch.Icon = t; - } - yield return null; - } - m_RequestedIcons.RemoveAll(i => m_Sketches[i].Icon != null); - } - } - - private static string CacheDir(SketchSetType type) - { - switch (type) - { - case SketchSetType.Liked: - { - // Ids are in the format "people/123456" so just pull out the numeric part - string id = App.GoogleIdentity.Profile.id; - id = id.Substring(id.LastIndexOf('/') + 1); - return Path.Combine(Application.persistentDataPath, String.Format("users/{0}/liked", id)); - } - case SketchSetType.Curated: - return Path.Combine(Application.persistentDataPath, "Curated Sketches"); - default: - return null; - } - } - - // When we sort the sketches, we sort them into buckets while retaining order within those - // buckets. We bucket the sketches using the gltf triangle count, but how we bucket depends on - // whether we are sorting the liked sketches or the curated sketches. - // Liked sketches get split into normal, complex (requires a warning), and impossible. - // Curated sketches get bucketed by the nearest 100,000 triangles. - private static int CompareSketchesByTriangleCountAndDownloadIndex(PolySketch a, PolySketch b) - { - int compareResult = CloudSketchComplexityBucket(a).CompareTo(CloudSketchComplexityBucket(b)); - - // If both sketches are in the same grouping, sort them relative to download index. - if (compareResult == 0) - { - return a.m_DownloadIndex.CompareTo(b.m_DownloadIndex); - } - - return compareResult; - } - - // Buckets the sketches into buckets 100000 tris in size. - private static int CloudSketchComplexityBucket(PolySketch s) - { - return s.PolySceneFileInfo.GltfTriangleCount / 100000; - } - } - - public class PolySceneFileInfo : SceneFileInfo - { - - // Asset - private string m_AssetId; - private string m_HumanName; - private string m_License; - - private string m_localTiltFile; - private string m_localIcon; - private string m_TiltFileUrl; - private string m_IconUrl; - private int m_GltfTriangleCount; - - private TiltFile m_DownloadedFile; - private bool m_IconDownloaded; - - // Populate metadata from the JSON returned by Poly for a single asset - // See go/vr-assets-service-api - public PolySceneFileInfo(JToken json) - { - m_AssetId = json["name"].ToString().Substring(7); // strip 'assets/' from start - m_HumanName = json["displayName"].ToString(); - - var format = json["formats"].First(x => x["formatType"].ToString() == "TILT")["root"]; - m_TiltFileUrl = format["url"].ToString(); - m_IconUrl = json["thumbnail"]?["url"]?.ToString(); - m_License = json["license"]?.ToString(); - - - // Some assets (old ones? broken ones?) are missing the "formatComplexity" field - var gltfFormat = json["formats"].First(x => x["formatType"].ToString() == "GLTF"); - string gltfTriCount = gltfFormat?["formatComplexity"]?["triangleCount"]?.ToString(); - if (gltfTriCount == null) - { - Debug.Log($"{m_AssetId} has no tricount"); - } - m_GltfTriangleCount = Int32.Parse(gltfTriCount ?? "1"); - - m_DownloadedFile = null; - m_IconDownloaded = false; - } - - public override string ToString() - { - return $"CloudFile {AssetId} file {TiltPath}"; - } - - public FileInfoType InfoType - { - get { return FileInfoType.Cloud; } - } - - public string HumanName - { - get { return m_HumanName; } - } - - // Allow setting since it is not in the asset json object itself - public string Author { get; set; } - - public bool Valid - { - get { return true; } - } - - public bool Available - { - get { return m_DownloadedFile != null; } - } - - public string FullPath - { - get { return m_localTiltFile; } - } - - public bool Exists - { - get { return true; } - } - - public bool ReadOnly - { - get { return true; } - } - - public string SourceId - { - get { return null; } - } - - public void Delete() - { - throw new NotImplementedException(); - } - - public string Rename(string newName) - { - throw new NotImplementedException(); - } - - public bool IsHeaderValid() - { - // Assume it's valid until we download it - return true; - } - - // Cloud specific stuff - public string AssetId - { - get { return m_AssetId; } - } - - public string TiltFileUrl - { - get { return m_TiltFileUrl; } - } - - public string IconUrl - { - get { return m_IconUrl; } - } - - public string License - { - get { return m_License; } - } - - // Path to the locally downloaded .tilt file - public string TiltPath - { - get { return m_localTiltFile; } - set { m_localTiltFile = value; } - } - - // Path to the locally downloaded icon - public string IconPath - { - get { return m_localIcon; } - set { m_localIcon = value; } - } - - public bool IconDownloaded - { - get { return m_IconDownloaded; } - set { m_IconDownloaded = value; } - } - - public bool TiltDownloaded - { - get { return m_DownloadedFile != null; } - set - { - if (value) - { - m_DownloadedFile = new TiltFile(m_localTiltFile); - } - else - { - m_DownloadedFile = null; - } - } - } - - // Not part of the interface - public int? TriangleCount => m_GltfTriangleCount; - - public Stream GetReadStream(string subfileName) - { - return m_DownloadedFile.GetReadStream(subfileName); - } - - // Not part of the interface - public int GltfTriangleCount => m_GltfTriangleCount; - } -} // namespace TiltBrush +// Copyright 2020 The Tilt Brush Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// 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 UnityEngine.Networking; +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Newtonsoft.Json.Linq; + +namespace TiltBrush +{ + + // TODO: Specify tag for which sketches to query (curated, liked etc.) + public class IcosaSketchSet : SketchSet + { + + const int kDownloadBufferSize = 1024 * 1024; // 1MB + + // Downloading is handled by IcosaSketchSet which will set the local paths + + private class IcosaSketch : Sketch + { + // This value holds the count of sketches that were downloaded by the sketch set + // before this one. It's used during our sort to retain order from Icosa, while + // allowing a custom sort on top. + public int m_DownloadIndex; + private IcosaSceneFileInfo m_FileInfo; + private Texture2D m_Icon; + + public SceneFileInfo SceneFileInfo + { + get { return m_FileInfo; } + } + + public string[] Authors + { + get + { + return m_FileInfo.Author != null + ? new string[] { m_FileInfo.Author } + : new string[] { }; + } + } + + public Texture2D Icon + { + get { return m_Icon; } + set { m_Icon = value; } + } + + public bool IconAndMetadataValid + { + get { return m_Icon != null; } + } + + public IcosaSketch(IcosaSceneFileInfo info) + { + m_FileInfo = info; + } + + public void UnloadIcon() + { + UnityEngine.Object.Destroy(m_Icon); + m_Icon = null; + } + + // Not part of the interface + public IcosaSceneFileInfo IcosaSceneFileInfo + { + get { return m_FileInfo; } + } + } + + private const string kIntroSketchAssetId = "agqmaia62KE"; + private const int kIntroSketchIndex = 1; + + private List m_Sketches; + private Dictionary m_AssetIds; + private int m_TotalCount = 0; + private VrAssetService m_AssetService; + private MonoBehaviour m_Parent; + private bool m_Ready; + private bool m_RefreshRequested; + private bool m_NeedsLogin; + private bool m_LoggedIn; + private bool m_ActivelyRefreshingSketches; + private int m_MaximumSceneTriangles; + + private SketchSetType m_Type; + private string m_CacheDir; + private Coroutine m_RefreshCoroutine; + private float m_CooldownTimer; + private List m_RequestedIcons = new List(); + private Coroutine m_TextureLoaderCoroutine; + + public SketchSetType Type { get { return m_Type; } } + + public VrAssetService VrAssetService + { + set { m_AssetService = value; } + } + + public IcosaSketchSet(MonoBehaviour parent, SketchSetType type, int maxSceneTriangles, + bool needsLogin = false) + { + m_Parent = parent; + m_Sketches = new List(); + m_AssetIds = new Dictionary(); + m_Ready = false; + m_RefreshRequested = false; + m_Type = type; + m_NeedsLogin = needsLogin; + m_MaximumSceneTriangles = maxSceneTriangles; + } + + public void Init() + { + VrAssetService = VrAssetService.m_Instance; + m_LoggedIn = false; + m_RefreshRequested = true; + m_CooldownTimer = VrAssetService.m_Instance.m_SketchbookRefreshInterval; + } + + public bool IsReadyForAccess + { + get { return m_Ready; } + } + + public bool IsActivelyRefreshingSketches + { + get { return m_ActivelyRefreshingSketches; } + private set + { + m_ActivelyRefreshingSketches = value; + OnSketchRefreshingChanged(); + } + } + + public bool RequestedIconsAreLoaded + { + get { return false; } + } + + public int NumSketches + { + get { return m_TotalCount; } + } + + public void NotifySketchCreated(string fullpath) { } + + public void NotifySketchChanged(string fullpath) { } + + public void RequestRefresh() + { + m_RefreshRequested = true; + } + + public bool IsSketchIndexValid(int index) + { + return index >= 0 && index < m_TotalCount; + } + + public void RequestOnlyLoadedMetadata(List requests) + { + // Stop any current texture loading + if (m_TextureLoaderCoroutine != null) + { + m_Parent.StopCoroutine(m_TextureLoaderCoroutine); + m_TextureLoaderCoroutine = null; + } + // Nuke textures on all icons + foreach (var sketch in m_Sketches) + { + sketch.UnloadIcon(); + } + m_RequestedIcons.Clear(); + m_RequestedIcons.AddRange(requests); + m_TextureLoaderCoroutine = m_Parent.StartCoroutine(TextureLoaderCoroutine()); + } + + public bool GetSketchIcon(int iSketchIndex, out Texture2D icon, out string[] authors, + out string description) + { + description = null; + if (iSketchIndex >= m_Sketches.Count) + { + icon = null; + authors = null; + return false; + } + IcosaSketch sketch = m_Sketches[iSketchIndex]; + icon = sketch.Icon; + authors = sketch.Authors; + return icon != null; + } + + public SceneFileInfo GetSketchSceneFileInfo(int i) + { + return i < m_Sketches.Count ? m_Sketches[i].SceneFileInfo : null; + } + + public string GetSketchName(int i) + { + return i < m_Sketches.Count ? m_Sketches[i].SceneFileInfo.HumanName : null; + } + + public void RenameSketch(int toRename, string newName) + { + throw new NotImplementedException(); + } + + public void PrecacheSketchModels(int i) + { + if (i < m_Sketches.Count) + { + App.IcosaAssetCatalog.PrecacheModels(m_Sketches[i].SceneFileInfo, $"IcosaSketchSet {i}"); + } + } + + public void DeleteSketch(int toDelete) + { + throw new NotImplementedException(); + } + + public void Update() + { + if (!VrAssetService.m_Instance.Available) + { + return; + } + + if (m_NeedsLogin) + { + bool loggedIn = App.IcosaIsLoggedIn; + if (loggedIn != m_LoggedIn) + { + m_LoggedIn = loggedIn; + if (!loggedIn) + { + if (m_RefreshCoroutine != null) + { + m_Parent.StopCoroutine(m_RefreshCoroutine); + IsActivelyRefreshingSketches = false; + m_RefreshCoroutine = null; + m_Sketches.Clear(); + m_AssetIds.Clear(); + m_TotalCount = 0; + m_CacheDir = null; + OnChanged(); + } + } + else + { + // Lie about refreshing. The refresh coroutine will happen in time, but + // for the user, we want them to know something will happen [soon]. + IsActivelyRefreshingSketches = true; + m_RefreshCoroutine = m_Parent.StartCoroutine(PeriodicRefreshCoroutine()); + } + } + } + else if (m_RefreshRequested && m_RefreshCoroutine == null) + { + m_RefreshCoroutine = m_Parent.StartCoroutine(PeriodicRefreshCoroutine()); + } + } + + public event Action OnChanged = delegate { }; + + public event Action OnSketchRefreshingChanged = delegate { }; + + private IEnumerator PeriodicRefreshCoroutine() + { + while (true) + { + if (m_RefreshRequested) + { + yield return Refresh(); + m_RefreshRequested = false; + + // Don't poll the showcase + if (Type == SketchSetType.Curated) + { + yield break; + } + m_CooldownTimer = VrAssetService.m_Instance.m_SketchbookRefreshInterval; + } + else + { + yield return null; + } + while (m_CooldownTimer > 0.0f) + { + m_CooldownTimer -= Time.deltaTime; + yield return null; + } + } + } + + // Update our state from the cloud. + // There are three stages to this, each with a separate coroutine: + // 1: Pull all the metadata from the server and populate m_Sketches + // If there are changes: + // 2: Download any thumbnails and tilt files we don't already have + // 3: Clean up any cached files that are no longer referenced + private IEnumerator Refresh() + { + if (m_NeedsLogin && !m_LoggedIn) + { + m_Sketches.Clear(); + m_AssetIds.Clear(); + m_TotalCount = 0; + m_CacheDir = null; + OnChanged(); + yield break; + } + + if (m_CacheDir == null) + { + m_CacheDir = CacheDir(Type); + try + { + Directory.CreateDirectory(m_CacheDir); + } + catch (Exception ex) + { + // Most of the system exceptions returned by CreateDirectory are just things the user needs + // to fix, and may well be sorted by reinstalling. If it's an ArgumentNullExeption or not a + // SystemException, we need to know about it, so log the exception. + if (!(ex is SystemException) || ex is ArgumentNullException) + { + Debug.LogException(ex); + } + ControllerConsoleScript.m_Instance.AddNewLine( + $"Error creating cache directory. Try restarting {App.kAppDisplayName}.\n" + + $"If this error persists, try reinstalling {App.kAppDisplayName}.", true); + yield break; + } + } + + // While we're fetching metadata, hold a flag so we can message state in the UI. + IsActivelyRefreshingSketches = true; + yield return PopulateSketchesCoroutine(); + IsActivelyRefreshingSketches = false; + } + + // Fetch asset metadata from server and populate m_Sketches + private IEnumerator PopulateSketchesCoroutine() + { + // Replacement data structures that will be populated with incoming data. These + // temporary structures will be copied to the "live" structures in chunks, so + // beware of modifications that may reference incomplete data. + List sketches = new List(); + Dictionary assetIds = new Dictionary(); + + bool fromEmpty = m_AssetIds.Count == 0; + int loadSketchCount = 0; + + AssetLister lister = null; + List infos = new List(); + + // If we don't have a connection to Icosa and we're querying the Showcase, use + // the json metadatas stored in resources, instead of trying to get them from Icosa. + if (VrAssetService.m_Instance.m_UseLocalFeaturedSketches && m_Type == SketchSetType.Curated) + { + TextAsset[] textAssets = + Resources.LoadAll(SketchCatalog.kDefaultShowcaseSketchesFolder); + for (int i = 0; i < textAssets.Length; ++i) + { + JObject jo = JObject.Parse(textAssets[i].text); + infos.Add(new IcosaSceneFileInfo(jo)); + } + } + else + { + lister = m_AssetService.ListAssets(Type); + } + + bool changed = false; + int pagesFetched = 0; + while (lister == null || lister.HasMore || assetIds.Count == 0) + { + if (sketches.Count >= 180) + { + break; // Don't allow the sketchbook to become too big. + } + + // lister will be null if we can't connect to Icosa and we've pre-populated infos + // with data from Resources. + if (lister != null) + { + using (var cr = lister.NextPage(infos)) + { + while (true) + { + try + { + if (!cr.MoveNext()) + { + break; + } + } + catch (VrAssetServiceException e) + { + ControllerConsoleScript.m_Instance.AddNewLine(e.UserFriendly); + Debug.LogException(e); + yield break; + } + yield return cr.Current; + } + } + } + if (infos.Count == 0) + { + break; + } + if (m_CacheDir == null) + { + yield break; + } + // Only cull the curated sketches. If a user likes a sketch that's very high poly count, + // there's no feedback to tell them why it didn't show up in their list. b/123649719 + if (m_Type == SketchSetType.Curated) + { + infos = infos.Where(x => x.GltfTriangleCount < m_MaximumSceneTriangles).ToList(); + } + if (m_Type == SketchSetType.Curated && !assetIds.Keys.Contains(kIntroSketchAssetId)) + { + yield return VrAssetService.m_Instance.InsertSketchInfo( + kIntroSketchAssetId, kIntroSketchIndex, infos); + } + for (int i = 0; i < infos.Count; i++) + { + IcosaSceneFileInfo info = infos[i]; + IcosaSketch sketch; + if (m_AssetIds.TryGetValue(info.AssetId, out sketch)) + { + // We already have this sketch + } + else + { + sketch = new IcosaSketch(info); + sketch.m_DownloadIndex = loadSketchCount++; + // Set local paths + info.TiltPath = Path.Combine(m_CacheDir, String.Format("{0}.tilt", info.AssetId)); + info.IconPath = Path.Combine(m_CacheDir, String.Format("{0}.png", info.AssetId)); + changed = true; + } + if (assetIds.ContainsKey(info.AssetId)) + { + Debug.LogWarning($"VR Asset Service has returned two objects for: {info.AssetId} {info.HumanName}"); + } + else + { + sketches.Add(sketch); + assetIds.Add(info.AssetId, sketch); + } + } + infos.Clear(); + + // Only download the files with every other page, otherwise the sketch pages change too often, + // Which results in a bad user experience. + if ((++pagesFetched & 1) == 0 || lister == null || !lister.HasMore) + { + if (Type == SketchSetType.Curated) + { + sketches.Sort(CompareSketchesByTriangleCountAndDownloadIndex); + } + + // If populating the set from new then show stuff as it comes in. + // (We don't have to worry about anything being removed) + if (fromEmpty) + { + yield return DownloadFilesCoroutine(sketches); + RemoveFailedDownloads(sketches); + // Copying sketches to m_Sketches before sketches has completed populating is a bit + // dangerous, but as long as they're copied and then listeners are notified + // immediately afterward with OnChanged(), there data should be stable. + m_TotalCount = sketches.Count; + m_Sketches = new List(sketches); + m_AssetIds = assetIds; + m_Ready = true; + OnChanged(); + } + } + } + + if (!fromEmpty) + { + // Find anything that was removed + int removed = m_Sketches.Count(s => !assetIds.ContainsKey(s.IcosaSceneFileInfo.AssetId)); + if (removed > 0) + { + changed = true; + } + + // Download new files before we notify our listeners that we've got new stuff for them. + if (changed) + { + yield return DownloadFilesCoroutine(sketches); + RemoveFailedDownloads(sketches); + } + + // DeleteOldSketchesCoroutine relies on m_AssetIds being up to date, so set these before + // we try to cull the herd. + m_AssetIds = assetIds; + if (changed) + { + yield return DeleteOldSketchesCoroutine(); + } + + // Set new data live + m_TotalCount = sketches.Count; + m_Sketches = new List(sketches); + m_Ready = true; + if (changed) + { + OnChanged(); + } + } + else + { + // On first run populate, take the time to clean out any cobwebs. + // Note that this is particularly important for the curated sketches, which do not have + // a periodic refresh, meaning old sketches will never been deleted in the other path. + yield return DeleteOldSketchesCoroutine(); + OnChanged(); + } + } + + // If we have not managed to download a tilt file or its icon, we should remove it from the + // sketches list so as not to confuse the user. + private void RemoveFailedDownloads(List sketches) + { + sketches.RemoveAll(x => !x.IcosaSceneFileInfo.TiltDownloaded || + !x.IcosaSceneFileInfo.IconDownloaded); + } + + // Download tilt files and thumbnails (that we don't already have) + private IEnumerator DownloadFilesCoroutine(List sketches) + { + bool notifyOnError = true; + void NotifyCreateError(IcosaSceneFileInfo sceneFileInfo, string type, Exception ex) + { + string error = $"Error downloading {type} file for {sceneFileInfo.HumanName}."; + ControllerConsoleScript.m_Instance.AddNewLine(error, notifyOnError); + notifyOnError = false; + Debug.LogException(ex); + Debug.LogError($"{sceneFileInfo.HumanName} {sceneFileInfo.TiltPath}"); + } + + void NotifyWriteError(IcosaSceneFileInfo sceneFileInfo, string type, UnityWebRequest www) + { + string error = $"Error downloading {type} file for {sceneFileInfo.HumanName}.\n" + + "Out of disk space?"; + ControllerConsoleScript.m_Instance.AddNewLine(error, notifyOnError); + notifyOnError = false; + Debug.LogError($"{www.error} {sceneFileInfo.HumanName} {sceneFileInfo.TiltPath}"); + } + + byte[] downloadBuffer = new byte[kDownloadBufferSize]; + // Load the icons first, then the thumbnails + foreach (IcosaSketch sketch in sketches) + { + IcosaSceneFileInfo sceneFileInfo = sketch.IcosaSceneFileInfo; + // TODO(b/36270116): Check filesizes when Icosa can give it to us to detect incomplete downloads + if (!sceneFileInfo.IconDownloaded) + { + if (File.Exists(sceneFileInfo.IconPath)) + { + sceneFileInfo.IconDownloaded = true; + } + else + { + using (UnityWebRequest www = UnityWebRequest.Get(sceneFileInfo.IconUrl)) + { + DownloadHandlerFastFile downloadHandler; + try + { + downloadHandler = new DownloadHandlerFastFile(sceneFileInfo.IconPath, downloadBuffer); + } + catch (Exception ex) + { + NotifyCreateError(sceneFileInfo, "icon", ex); + continue; + } + www.downloadHandler = downloadHandler; + yield return www.SendWebRequest(); + if (www.isNetworkError || www.responseCode >= 400 || !string.IsNullOrEmpty(www.error)) + { + NotifyWriteError(sceneFileInfo, "icon", www); + } + else + { + sceneFileInfo.IconDownloaded = true; + } + } + } + } + yield return null; + } + + foreach (IcosaSketch sketch in sketches) + { + IcosaSceneFileInfo sceneFileInfo = sketch.IcosaSceneFileInfo; + if (!sceneFileInfo.TiltDownloaded) + { + if (File.Exists(sceneFileInfo.TiltPath)) + { + sceneFileInfo.TiltDownloaded = true; + } + else + { + using (UnityWebRequest www = UnityWebRequest.Get(sceneFileInfo.TiltFileUrl)) + { + DownloadHandlerFastFile downloadHandler; + try + { + downloadHandler = new DownloadHandlerFastFile(sceneFileInfo.TiltPath, downloadBuffer); + } + catch (Exception ex) + { + NotifyCreateError(sceneFileInfo, "sketch", ex); + continue; + } + www.downloadHandler = downloadHandler; + yield return www.SendWebRequest(); + if (www.isNetworkError || www.responseCode >= 400 || !string.IsNullOrEmpty(www.error)) + { + NotifyWriteError(sceneFileInfo, "sketch", www); + } + else + { + sceneFileInfo.TiltDownloaded = true; + } + } + } + } + yield return null; + } + yield return null; + } + + // Delete any files that aren't referenced in m_Sketches (actually m_AssetIds) + // Does this on a background thread so prevent hitches. + private IEnumerator DeleteOldSketchesCoroutine() + { + if (m_CacheDir != null) + { + var task = new Future(() => + { + var unknown = new DirectoryInfo(m_CacheDir).GetFiles().Where( + f => !m_AssetIds.ContainsKey(Path.GetFileNameWithoutExtension(f.Name))); + foreach (var f in unknown) + { + f.Delete(); + } + return true; + }); + + bool unused; + while (!task.TryGetResult(out unused)) + { + yield return null; + } + } + } + + // Read the icon textures for all sketches in m_RequestedIcons + private IEnumerator TextureLoaderCoroutine() + { + while (m_RequestedIcons.Count > 0) + { + foreach (int i in m_RequestedIcons) + { + IcosaSketch sketch = m_Sketches[i]; + string path = sketch.IcosaSceneFileInfo.IconPath; + if (sketch.IcosaSceneFileInfo.IconDownloaded) + { + byte[] data = File.ReadAllBytes(path); + Texture2D t = new Texture2D(2, 2); + t.LoadImage(data); + sketch.Icon = t; + } + yield return null; + } + m_RequestedIcons.RemoveAll(i => m_Sketches[i].Icon != null); + } + } + + private static string CacheDir(SketchSetType type) + { + switch (type) + { + case SketchSetType.Liked: + { + string id = App.IcosaUserId; + return Path.Combine(Application.persistentDataPath, String.Format("users/{0}/liked", id)); + } + case SketchSetType.Curated: + return Path.Combine(Application.persistentDataPath, "Curated Sketches"); + default: + return null; + } + } + + // When we sort the sketches, we sort them into buckets while retaining order within those + // buckets. We bucket the sketches using the gltf triangle count, but how we bucket depends on + // whether we are sorting the liked sketches or the curated sketches. + // Liked sketches get split into normal, complex (requires a warning), and impossible. + // Curated sketches get bucketed by the nearest 100,000 triangles. + private static int CompareSketchesByTriangleCountAndDownloadIndex(IcosaSketch a, IcosaSketch b) + { + int compareResult = CloudSketchComplexityBucket(a).CompareTo(CloudSketchComplexityBucket(b)); + + // If both sketches are in the same grouping, sort them relative to download index. + if (compareResult == 0) + { + return a.m_DownloadIndex.CompareTo(b.m_DownloadIndex); + } + + return compareResult; + } + + // Buckets the sketches into buckets 100000 tris in size. + private static int CloudSketchComplexityBucket(IcosaSketch s) + { + return s.IcosaSceneFileInfo.GltfTriangleCount / 100000; + } + } + + public class IcosaSceneFileInfo : SceneFileInfo + { + + // Asset + private string m_AssetId; + private string m_HumanName; + private string m_License; + + private string m_localTiltFile; + private string m_localIcon; + private string m_TiltFileUrl; + private string m_IconUrl; + private int m_GltfTriangleCount; + + private TiltFile m_DownloadedFile; + private bool m_IconDownloaded; + + public bool IsValid => m_TiltFileUrl != null; + + // Populate metadata from the JSON returned by Icosa for a single asset + // See go/vr-assets-service-api + public IcosaSceneFileInfo(JToken json) + { + m_AssetId = json["assetId"].ToString(); + m_HumanName = json["displayName"].ToString(); + + var format = json["formats"].First(x => x["formatType"].ToString() == "TILT")["root"]; + m_TiltFileUrl = format["url"].ToString(); + m_IconUrl = json["thumbnail"]?["url"]?.ToString(); + m_License = json["license"]?.ToString(); + + // Some assets (old ones? broken ones?) are missing the "formatComplexity" field + var gltfFormat = json["formats"].FirstOrDefault(x => + x["formatType"].ToString() == "GLTF2" || x["formatType"].ToString() == "GLTF" + ); + string gltfTriCount = gltfFormat?["formatComplexity"]?["triangleCount"]?.ToString(); + m_GltfTriangleCount = Int32.Parse(gltfTriCount ?? "1"); + + m_DownloadedFile = null; + m_IconDownloaded = false; + } + + public override string ToString() + { + return $"CloudFile {AssetId} file {TiltPath}"; + } + + public FileInfoType InfoType + { + get { return FileInfoType.Cloud; } + } + + public string HumanName + { + get { return m_HumanName; } + } + + // Allow setting since it is not in the asset json object itself + public string Author { get; set; } + + public bool Valid + { + get { return true; } + } + + public bool Available + { + get { return m_DownloadedFile != null; } + } + + public string FullPath + { + get { return m_localTiltFile; } + } + + public bool Exists + { + get { return true; } + } + + public bool ReadOnly + { + get { return true; } + } + + public string SourceId + { + get { return null; } + } + + public void Delete() + { + throw new NotImplementedException(); + } + + public string Rename(string newName) + { + throw new NotImplementedException(); + } + + public bool IsHeaderValid() + { + // Assume it's valid until we download it + return true; + } + + // Cloud specific stuff + public string AssetId + { + get { return m_AssetId; } + } + + public string TiltFileUrl + { + get { return m_TiltFileUrl; } + } + + public string IconUrl + { + get { return m_IconUrl; } + } + + public string License + { + get { return m_License; } + } + + // Path to the locally downloaded .tilt file + public string TiltPath + { + get { return m_localTiltFile; } + set { m_localTiltFile = value; } + } + + // Path to the locally downloaded icon + public string IconPath + { + get { return m_localIcon; } + set { m_localIcon = value; } + } + + public bool IconDownloaded + { + get { return m_IconDownloaded; } + set { m_IconDownloaded = value; } + } + + public bool TiltDownloaded + { + get { return m_DownloadedFile != null; } + set + { + if (value) + { + m_DownloadedFile = new TiltFile(m_localTiltFile); + } + else + { + m_DownloadedFile = null; + } + } + } + + // Not part of the interface + public int? TriangleCount => m_GltfTriangleCount; + + public Stream GetReadStream(string subfileName) + { + return m_DownloadedFile.GetReadStream(subfileName); + } + + // Not part of the interface + public int GltfTriangleCount => m_GltfTriangleCount; + } +} // namespace TiltBrush diff --git a/Assets/Scripts/Sharing/PolySketchSet.cs.meta b/Assets/Scripts/Sharing/IcosaSketchSet.cs.meta similarity index 100% rename from Assets/Scripts/Sharing/PolySketchSet.cs.meta rename to Assets/Scripts/Sharing/IcosaSketchSet.cs.meta diff --git a/Assets/Scripts/Sharing/OAuth2Identity.cs b/Assets/Scripts/Sharing/OAuth2Identity.cs index a9e66905c9..5bafccbb0b 100644 --- a/Assets/Scripts/Sharing/OAuth2Identity.cs +++ b/Assets/Scripts/Sharing/OAuth2Identity.cs @@ -102,6 +102,7 @@ private static void LogOutAll() private OAuth2CredentialRequest m_CredentialRequest; public bool IsGoogle => m_Service == SecretsConfig.Service.Google; + public bool IsIcosa => m_Service == SecretsConfig.Service.Icosa; public UserCredential UserCredential => m_CredentialRequest?.UserCredential; private SecretsConfig.ServiceAuthData ServiceAuthData => App.Config.Secrets[m_Service]; public string ClientId => ServiceAuthData?.ClientId; @@ -228,7 +229,7 @@ public async Task ReauthorizeAsync() public async void LoginAsync() { - if (string.IsNullOrEmpty(ClientId) || string.IsNullOrEmpty(ClientSecret)) + if (!IsIcosa && (string.IsNullOrEmpty(ClientId) || string.IsNullOrEmpty(ClientSecret))) { Debug.LogWarning( $"Attempted to log in to {m_Service} with missing Client Id or Client Secret."); diff --git a/Assets/Scripts/Sharing/UploadPopUpWindow.cs b/Assets/Scripts/Sharing/UploadPopUpWindow.cs index a0732b4d29..7bdf75818a 100644 --- a/Assets/Scripts/Sharing/UploadPopUpWindow.cs +++ b/Assets/Scripts/Sharing/UploadPopUpWindow.cs @@ -14,6 +14,7 @@ using System; using UnityEngine; +using UnityEngine.Serialization; using GlobalCommands = TiltBrush.SketchControlsScript.GlobalCommands; namespace TiltBrush @@ -32,7 +33,7 @@ private enum DisplayMode UploadFailed, UploadingDenied, Waiting, - EmbeddedMediaWarningPoly, + EmbeddedMediaWarningIcosa, EmbeddedMediaWarningSketchfab, NothingToUploadWarning, ConnectionError, @@ -46,13 +47,13 @@ private enum DisplayMode // Things that should be visible when confirming upload. [SerializeField] private GameObject m_ConfirmObjects; - [SerializeField] private GameObject m_PolyLoggedInObjects; - [SerializeField] private GameObject m_PolyLoggedOutObjects; + [SerializeField] private GameObject m_IcosaLoggedInObjects; + [SerializeField] private GameObject m_IcosaLoggedOutObjects; [SerializeField] private GameObject m_SketchfabLoggedInObjects; [SerializeField] private GameObject m_SketchfabLoggedOutObjects; - [SerializeField] private TMPro.TextMeshPro m_PolyUserName; + [SerializeField] private TMPro.TextMeshPro m_IcosaUserName; [SerializeField] private TMPro.TextMeshPro m_SketchfabUserName; - [SerializeField] private Renderer m_GooglePhoto; + [SerializeField] private Renderer m_IcosaPhoto; [SerializeField] private Renderer m_SketchfabPhoto; // Things that should be visible when uploading. @@ -72,7 +73,7 @@ private enum DisplayMode [SerializeField] private GameObject m_WaitObjects; // Things that should be visible when media library content is in the scene. - [SerializeField] private GameObject m_EmbeddedMediaWarningPoly; + [SerializeField] private GameObject m_EmbeddedMediaWarningIcosa; [SerializeField] private GameObject m_EmbeddedMediaWarningSketchfab; // Things that should be visible when there's nothing to upload. @@ -81,7 +82,7 @@ private enum DisplayMode // Things that should be visible when there has been a connection error. [SerializeField] private GameObject m_ConnectionErrorObjects; - // Things that should be visible when Tilt Brush can't talk to Poly because it is + // Things that should be visible when Open Brush can't talk to Icosa because it is // out of date. [SerializeField] private GameObject m_OutOfDateObjects; @@ -100,7 +101,7 @@ public override void Init(GameObject rParent, string sText) InitUI(); OAuth2Identity.ProfileUpdated += OnProfileUpdated; - RefreshUploadButton(Cloud.Poly); + RefreshUploadButton(Cloud.Icosa); RefreshUploadButton(Cloud.Sketchfab); m_OnClose += OnClose; @@ -123,7 +124,7 @@ private void SetMode(DisplayMode displayMode) m_UploadFailedObjects.SetActive(displayMode == DisplayMode.UploadFailed); m_UploadingDeniedObjects.SetActive(displayMode == DisplayMode.UploadingDenied); m_WaitObjects.SetActive(displayMode == DisplayMode.Waiting); - m_EmbeddedMediaWarningPoly.SetActive(displayMode == DisplayMode.EmbeddedMediaWarningPoly); + m_EmbeddedMediaWarningIcosa.SetActive(displayMode == DisplayMode.EmbeddedMediaWarningIcosa); m_EmbeddedMediaWarningSketchfab.SetActive( displayMode == DisplayMode.EmbeddedMediaWarningSketchfab); m_NothingToUploadWarning.SetActive(displayMode == DisplayMode.NothingToUploadWarning); @@ -147,13 +148,13 @@ private void InitUI() m_LoggingInType = Cloud.None; SetMode(DisplayMode.Blank); - { // Turn off the poly option - (var name, var inEl, var outEl, var photo) = GetUiFor(Cloud.Poly); - name.gameObject.SetActive(false); - inEl.SetActive(false); - outEl.SetActive(false); - photo.gameObject.SetActive(false); - } + // { // Turn off the Icosa option + // (var name, var inEl, var outEl, var photo) = GetUiFor(Cloud.Icosa); + // name.gameObject.SetActive(false); + // inEl.SetActive(false); + // outEl.SetActive(false); + // photo.gameObject.SetActive(false); + // } if (m_AssetService.UploadProgress <= 0.0f) { @@ -201,7 +202,7 @@ override protected void BaseUpdate() if (m_LoginOnDesktopObjects.activeSelf) { // Check to see if we just logged in. - if ((m_LoggingInType == Cloud.Poly && App.GoogleIdentity.LoggedIn) || + if ((m_LoggingInType == Cloud.Icosa && App.IcosaIsLoggedIn) || (m_LoggingInType == Cloud.Sketchfab && App.SketchfabIdentity.LoggedIn)) { SetMode(DisplayMode.Loggedout); @@ -261,31 +262,43 @@ override protected void BaseUpdate() case Cloud.Sketchfab: return (m_SketchfabUserName, m_SketchfabLoggedInObjects, m_SketchfabLoggedOutObjects, m_SketchfabPhoto); - case Cloud.Poly: - return (m_PolyUserName, m_PolyLoggedInObjects, - m_PolyLoggedOutObjects, m_GooglePhoto); + case Cloud.Icosa: + return (m_IcosaUserName, m_IcosaLoggedInObjects, + m_IcosaLoggedOutObjects, m_IcosaPhoto); default: throw new InvalidOperationException($"{cloud}"); } } void RefreshUploadButton(Cloud backend) { - if (backend == Cloud.Poly) { return; } var ui = GetUiFor(backend); - OAuth2Identity.UserInfo profile = App.GetIdentity(backend).Profile; - ui.loggedInElements.SetActive(profile != null); - ui.loggedOutElements.SetActive(profile == null); - - if (profile != null) + if (backend == Cloud.Icosa) { - ui.name.text = profile.name; - ui.photo.material.mainTexture = profile.icon; + bool icosaLoggedIn = App.IcosaIsLoggedIn; + ui.loggedInElements.SetActive(icosaLoggedIn); + ui.loggedOutElements.SetActive(!icosaLoggedIn); + if (icosaLoggedIn) + { + ui.name.text = App.IcosaUserName; + ui.photo.material.mainTexture = App.IcosaUserIcon; + } + } + else + { + OAuth2Identity.UserInfo profile = App.GetIdentity(backend).Profile; + ui.loggedInElements.SetActive(profile != null); + ui.loggedOutElements.SetActive(profile == null); + if (profile != null) + { + ui.name.text = profile.name; + ui.photo.material.mainTexture = profile.icon; + } } } void OnProfileUpdated(OAuth2Identity _) { - RefreshUploadButton(Cloud.Poly); + RefreshUploadButton(Cloud.Icosa); RefreshUploadButton(Cloud.Sketchfab); } @@ -300,8 +313,8 @@ void OnOperationStackChanged() // An embedded media warning only shows up if the user has tried to upload and there was non- // exportable content. So we only need to be concerned with the case that the embedded warning // is showing and is no longer relevant. - if (m_EmbeddedMediaWarningPoly.activeSelf && - !WidgetManager.m_Instance.HasNonExportableContent(Cloud.Poly)) + if (m_EmbeddedMediaWarningIcosa.activeSelf && + !WidgetManager.m_Instance.HasNonExportableContent(Cloud.Icosa)) { SetMode(DisplayMode.Confirming); } @@ -322,7 +335,6 @@ public void UserPressedLoginButton(int param) /// show a warning or error. public void UserPressedUploadButton(Cloud cloud, Action onSafeToUpload) { - Debug.Assert(cloud == Cloud.Sketchfab); // User attempted to upload, but make sure there's actually something to upload. if (!WidgetManager.m_Instance.HasExportableContent(cloud)) { diff --git a/Assets/Scripts/Sharing/VrAssetService.cs b/Assets/Scripts/Sharing/VrAssetService.cs index 63e1e518c1..665f12d668 100644 --- a/Assets/Scripts/Sharing/VrAssetService.cs +++ b/Assets/Scripts/Sharing/VrAssetService.cs @@ -1,878 +1,953 @@ -// Copyright 2020 The Tilt Brush Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// 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; -using System.Collections.Generic; -using System.IO; -using System.IO.Compression; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Newtonsoft.Json.Linq; -using UnityEngine; -using UnityEngine.Networking; - -namespace TiltBrush -{ - - /// Back-end for cloud upload - /// These values might be serialized into prefabs; do not change them! - /// Make serializable so they don't get mangled by obfuscation. - [Serializable] - public enum Cloud - { - None, - Poly, - Sketchfab - } - - [Serializable] - public enum VrAssetFormat - { - Unknown, - TILT, - GLTF, - GLTF2, - } - - public class VrAssetService : MonoBehaviour - { - // Constants - - const string kGltfName = "sketch.gltf"; - - public const string kApiHost = "https://poly.googleapis.com"; - private const string kAssetLandingPage = "https://vr.google.com/sketches/uploads/publish/"; - - private const string kListAssetsUri = "/v1/assets"; - private const string kUserAssetsUri = "/v1/users/me/assets"; - private const string kUserLikesUri = "/v1/users/me/likedassets"; - private const string kGetVersionUri = "/$discovery/rest?version=v1"; - - public static string kPolyApiKey => App.Config.GoogleSecrets?.ApiKey; - - public const string kCreativeCommonsLicense = "CREATIVE_COMMONS_BY"; - - // Poly API used by Tilt Brush. - // If Poly doesn't support this version, don't try to talk to Poly and prompt the user to upgrade. - private const string kPolyApiVersion = "v1"; - - /// Change-of-basis transform - public static readonly TrTransform kPolyFromUnity; - - private static Dictionary kGltfMimetypes = new Dictionary - { - { ".gltf", "model/gltf+json" }, - { ".bin", "application/octet-stream" }, - { ".glsl", "text/plain" }, - { ".bmp", "image/bmp" }, - { ".jpeg", "image/jpeg" }, - { ".jpg", "image/jpeg" }, - { ".png", "image/png" }, - { ".tilt", "application/octet-stream" } - }; - - // For progress reporting - private enum UploadStep - { - CreateGltf, - CreateTilt, - ZipElements, - UploadElements, - UpdateAssetData, - Done - } - - // These are progress values at the start of each step. - // TODO(b/146892613): have a different set for Poly vs Sketchfab? - private static double[] kProgressSteps = - { - 0.01, // UploadStep.CreateGltf -- progress > 0 means we have begun - 0.25, // UploadStep.CreateTilt - 0.3, // UploadStep.ZipElements - 0.5, // UploadStep.UploadElements - 0.95, // UploadStep.UpdateAssetData - 1, // UploadStep.Done - 1 // - }; - - // Classes and types - - class StreamWithReadProgress : WrappedStream - { - public int TotalRead { get; private set; } - public StreamWithReadProgress(string filename) - { - SetWrapped(File.OpenRead(filename), ownsStream: true); - } - public override int Read(byte[] buffer, int offset, int count) - { - var amountRead = base.Read(buffer, offset, count); - TotalRead += amountRead; - return amountRead; - } - public override int ReadByte() - { - var amountRead = base.ReadByte(); - TotalRead += amountRead; - return amountRead; - } - } - - /// A bag of information about a pending upload - class UploadInfo : IProgress - { - // Only one of sourceFile or sourceData is valid - public readonly FileInfo m_sourceFile; - public readonly byte[] m_sourceData; - public readonly string m_remoteName; - public readonly long m_length; - public string m_elementId; - public double m_uploadPercent = 0; - - public UploadInfo(string sourceFile, string remoteName) - { - m_sourceFile = new FileInfo(sourceFile); - m_remoteName = remoteName; - m_length = m_sourceFile.Length; - } - - public UploadInfo(byte[] data, string remoteName) - { - m_sourceData = data; - m_remoteName = remoteName; - m_length = data.Length; - } - - public void SetUploaded(string elementId) - { - m_elementId = elementId; - } - - /// Allocates and returns a new Stream. - /// Caller is responsible for disposing of it. - public Stream OpenStream() - { - if (m_sourceData != null) - { - return new MemoryStream(m_sourceData); - } - else - { - return m_sourceFile.OpenRead(); - } - } - - void IProgress.Report(double value) - { - m_uploadPercent = value; - } - } - - /// Creates and then cleans up a uniquely-named temporary directory - class TemporaryUploadDirectory : IDisposable - { - public string Value { get; } - - public TemporaryUploadDirectory() - { -#if UNITY_EDITOR - if (App.Config && App.Config.m_DebugUpload) - { - // Delay deleting the directory until the next upload - string dirName = Path.Combine(Application.temporaryCachePath, "Upload"); - if (Directory.Exists(dirName)) - { - try { Directory.Delete(dirName, true); } - catch (Exception e) { Debug.LogException(e); } - } - } -#endif - Value = FileUtils.GenerateNonexistentFilename( - Application.temporaryCachePath, "Upload", ""); - string failureMessage = $"Can't create upload directory: {Value}"; - bool dirCreated = FileUtils.InitializeDirectoryWithUserError(Value, failureMessage); - if (!dirCreated) - { - throw new VrAssetServiceException(failureMessage); - } - } - - public void Dispose() - { -#if UNITY_EDITOR - if (App.Config && App.Config.m_DebugUpload) - { - // Delay deleting the directory until the next upload - return; - } -#endif - if (Directory.Exists(Value)) - { - Directory.Delete(Value, true); - } - } - } - - // Static API - - public static VrAssetService m_Instance; - - // Currently this always returns the standard API host when running unit tests - public static string ApiHost - { - get - { - string cfg = App.UserConfig?.Sharing.VrAssetServiceHostOverride; - if (!string.IsNullOrEmpty(cfg)) { return cfg; } - return kApiHost; - } - } - - /// Returns true if Poly would accept a PATCH of the specified asset - /// from the specified user. - /// - /// Pass: - /// type - - /// Where you found the assetId. Necessary because of some shortcuts - /// taken by the implementation. - /// userId - Poly user id of the currently-logged-in OAuth user. Get it - /// with GetAccountIdAsync(). - public static async Task IsMutableAssetIdAsync( - FileInfoType type, string assetId, string userId, string apiHost) - { - if (assetId == null) { return false; } - // There are too many assumptions here -- for both cloud and disk, the logic - // should be "is it owned by me and unpublished? then it's mutable" - if (type == FileInfoType.Cloud) - { - // Assumption: cloud files are immutable. - // You can't "Like" an unpublished asset; and published assets are immutable. - return false; - } - else if (type == FileInfoType.Disk) - { - // Assumption: this asset is mutable because it's unlikely for a cloud-based .tilt - // to be in the user's Sketches/ folder. Local sketches always become un-published - // and mutable assets when uploaded (remember, publishing makes a copy). - // If someone grabbed a .tilt from their Poly asset cache and put it in Sketches/ - // that would break this assumption and I'm not sure what would happen. - if (userId == null) { return false; } - // It's mutable, but check whether it's mutable by _us_. - try - { - // The null == null case is handled earlier - WebRequest request = new WebRequest( - $"{apiHost}{kListAssetsUri}/{assetId}?key={kPolyApiKey}", - App.GoogleIdentity, UnityWebRequest.kHttpVerbGET); - return (await request.SendAsync()).JObject?["accountId"].ToString() == userId; - } - catch (VrAssetServiceException) - { - return false; - } - } - else - { - throw new InvalidOperationException($"Unknown FileInfoType {type}"); - } - } - - // Instance API - - static VrAssetService() - { - Matrix4x4 polyFromUnity = AxisConvention.GetFromUnity(AxisConvention.kGltfAccordingToPoly); - - // Provably non-lossy: the mat4 is purely TRS, and the S is uniform - kPolyFromUnity = TrTransform.FromMatrix4x4(polyFromUnity); - } - - // Instance API - - [SerializeField] private int m_AssetsPerPage; - [SerializeField] public float m_SketchbookRefreshInterval; - - private float m_UploadProgress; - private bool m_LastUploadFailed; - private string m_LastUploadErrorMessage; - private string m_LastUploadErrorDetails; - private bool m_UserCanceledLastUpload; - private string m_LastUploadCompleteUrl; - TaskAndCts<(string url, long bytes)> m_UploadTask = null; - - // Poly account id associated with the Google identity - private string m_PolyAccountId; - - private enum PolyStatus - { - Ok, - Disabled, - NoConnection - } - private PolyStatus m_PolyStatus; - - public bool Available => m_PolyStatus == PolyStatus.Ok; - - public bool NoConnection => m_PolyStatus == PolyStatus.NoConnection; - - public float UploadProgress => m_UploadProgress; - - public bool LastUploadFailed - { - get { return m_LastUploadFailed; } - } - - public string LastUploadErrorMessage - { - get { return m_LastUploadErrorMessage; } - } - - public string LastUploadErrorDetails - { - get { return m_LastUploadErrorDetails; } - } - - public bool UserCanceledLastUpload - { - get { return m_UserCanceledLastUpload; } - } - - public string LastUploadCompleteUrl - { - get { return m_LastUploadCompleteUrl; } - } - - private string AssetLandingPage - { - get - { - string cfg = App.UserConfig.Sharing.VrAssetServiceUrlOverride; - if (!string.IsNullOrEmpty(cfg)) { return cfg; } - return kAssetLandingPage; - } - } - - // Cannot be an UploadProgress setter because the getter's type is different. - // pct is how much of that step has been completed. - private void SetUploadProgress(UploadStep step, double pct) - { - var step0 = (float)kProgressSteps[Mathf.Min(kProgressSteps.Length - 1, (int)step)]; - var step1 = (float)kProgressSteps[Mathf.Min(kProgressSteps.Length - 1, (int)step + 1)]; - m_UploadProgress = Mathf.Lerp(step0, step1, (float)pct); - } - - void Awake() - { - m_Instance = this; - } - - void Start() - { - if (!string.IsNullOrEmpty(App.UserConfig.Sharing.VrAssetServiceHostOverride) || - !string.IsNullOrEmpty(App.UserConfig.Sharing.VrAssetServiceUrlOverride)) - { - Debug.LogFormat("Overriding VrAssetService Api Host: {0} Landing Page: {1}", - ApiHost, AssetLandingPage); - } - - // If auto profiling is enabled, disable automatic Poly downloading. - if (!App.UserConfig.Profiling.AutoProfile) - { - VerifyPolyConnectionAndCheckApiVersionAsync(); - } - else - { - m_PolyStatus = PolyStatus.Disabled; - } - } - - /// Consume the result of the previous upload (if any) - public void ConsumeUploadResults() - { - // Our UI interprets "progress >= 1.0" as "there are results and we must display them!" - // The UI should really be internally stateful, and only display these results when new results - // appear that haven't yet been shown to the user. The issue with this design is that there - // are other consumers of upload results. Thankfully, they are less important and don't - // care about progress; so the hack is that we only "consume" the progress. - if (m_UploadProgress >= 1) - { - m_UploadProgress = 0; - } - } - - /// If you try and upload a sketch while a sketch is already uploading, - /// the existing upload will be canceled. - public async Task UploadCurrentSketchAsync(Cloud backend, bool isDemoUpload) - { - // This function handles most of the setup and cleanup. - // The heavy lifting is split out into UploadCurrentSketchInternal. - - // Generic to all kinds of failures - void ReportFailure(string userFriendly, string fullMessage = "") - { - m_LastUploadFailed = true; - m_LastUploadErrorMessage = userFriendly; - m_LastUploadErrorDetails = fullMessage; - ControllerConsoleScript.m_Instance.AddNewLine(LastUploadErrorMessage, skipLog: true); - ControllerConsoleScript.m_Instance.AddNewLine(LastUploadErrorDetails, skipLog: true); - AudioManager.m_Instance.PlayUploadCanceledSound(InputManager.Wand.Transform.position); - } - - Debug.LogFormat("UploadCurrentSketch(demo: {0})", isDemoUpload); - - // Cancel previous upload coroutine if necessary. - if (m_UploadTask != null) - { - CancelUpload(); - if (await Task.WhenAny(m_UploadTask.Task, Task.Delay(TimeSpan.FromSeconds(5))) != - m_UploadTask.Task) - { - // Definitely a bug we should fix; make it noisy because otherwise it just looks - // like nothing is happening. - OutputWindowScript.Error("Timed out waiting for canceled upload"); - return; - } - } - - - m_LastUploadFailed = false; - m_LastUploadErrorMessage = ""; - m_LastUploadErrorDetails = ""; - m_UserCanceledLastUpload = false; - m_UploadProgress = 0.0f; - - using (var tempUploadDir = new TemporaryUploadDirectory()) - try - { - if (!isDemoUpload) - { - App.Instance.SetDesiredState(App.AppState.Uploading); - } - AudioManager.m_Instance.UploadLoop(true); - var timer = System.Diagnostics.Stopwatch.StartNew(); - m_UploadTask = new TaskAndCts<(string url, long bytes)>(); - Debug.Assert(backend == Cloud.Sketchfab); - m_UploadTask.Task = UploadCurrentSketchSketchfabAsync(m_UploadTask.Token, tempUploadDir.Value, - isDemoUpload); - var (url, totalUploadLength) = await m_UploadTask.Task; - m_LastUploadCompleteUrl = url; - ControllerConsoleScript.m_Instance.AddNewLine("Upload succeeded!"); - AudioManager.m_Instance.PlayUploadCompleteSound(InputManager.Wand.Transform.position); - PanelManager.m_Instance.GetAdminPanel().ActivatePromoBorder(true); - // Don't auto-open the URL on mobile because it steals focus from the user. - if (!isDemoUpload && !App.Config.IsMobileHardware && m_LastUploadCompleteUrl != null) - { - // Can't pass a string param because this is also called from mobile GUI - SketchControlsScript.m_Instance.IssueGlobalCommand( - SketchControlsScript.GlobalCommands.ViewLastUpload); - } - } - catch (VrAssetServiceException exception) - { - // "Expected" failures (40x, 50x, etc) - Debug.LogWarning("UploadCurrentSketch external error"); - Debug.LogException(exception); - ReportFailure(exception.UserFriendly, exception.Message); - } - catch (OperationCanceledException) - { - m_UserCanceledLastUpload = true; - ReportFailure("Upload canceled."); - } - catch (Exception exception) - { - // Unexpected failures -- ie, bugs on our part - Debug.LogError("UploadCurrentSketch internal error"); - ReportFailure("Upload failed.", exception.Message); - throw; - } - finally - { - // Cleanup - if (App.CurrentState == App.AppState.Uploading) - { - App.Instance.SetDesiredState(App.AppState.Standard); - } - - m_UploadTask = null; - AudioManager.m_Instance.UploadLoop(false); - // This is how the upload popup knows we're complete - m_UploadProgress = 1.0f; - } - } - - /// Request to cancel the upload -- does not happen synchronously. - public void CancelUpload() - { - m_UploadTask?.Cancel(); - } - - private async void VerifyPolyConnectionAndCheckApiVersionAsync() - { - m_PolyStatus = await GetPolyStatus(); - } - - private static async Task GetPolyStatus() - { - return PolyStatus.Disabled; - - // UserConfig override - if (App.UserConfig.Flags.DisablePoly || - string.IsNullOrEmpty(App.Config.GoogleSecrets?.ApiKey)) - { - return PolyStatus.Disabled; - } - - string uri = String.Format("{0}{1}", ApiHost, kGetVersionUri); - try - { - var result = (await new WebRequest(uri, App.GoogleIdentity).SendAsync()).JObject; - string version = result["version"].Value(); - if (version == kPolyApiVersion) - { - return PolyStatus.Ok; - } - else - { - Debug.LogWarning($"Poly requires API {version} > {kPolyApiVersion}"); - return PolyStatus.Disabled; - } - } - catch (VrAssetServiceException e) - { - Debug.LogWarning($"Error connecting to Poly: {e}"); - return PolyStatus.NoConnection; - } - catch (Exception e) - { - Debug.LogError($"Internal error connecting to Poly: {e}"); - return PolyStatus.NoConnection; - } - } - - /// Returns a writable SceneFileInfo - private DiskSceneFileInfo GetWritableFile() - { - // hermetic gltf files currently don't work with AccessLevel.PRIVATE - SceneFileInfo currentFileInfo = SaveLoadScript.m_Instance.SceneFile; - - DiskSceneFileInfo fileInfo; - if (currentFileInfo.Valid) - { - if (currentFileInfo is DiskSceneFileInfo) - { - fileInfo = (DiskSceneFileInfo)currentFileInfo; - } - else - { - // This is a cloud sketch not saved before - fileInfo = SaveLoadScript.m_Instance.GetNewNameSceneFileInfo(); - } - } - else - { - // Save as a new file - fileInfo = SaveLoadScript.m_Instance.GetNewNameSceneFileInfo(); - } - return fileInfo; - } - - /// Returns a relative path R such that Join(fromDir, R) refers to toFile, or null on error. - /// Does not handle ".." paths. - public static string GetRelativePath(string fromDir, string toFile) - { - // Normalize paths so we can use plain string compares - var alt = Path.AltDirectorySeparatorChar; - var standard = Path.DirectorySeparatorChar; - if (alt != standard) - { - fromDir = fromDir.Replace(alt, standard); - toFile = toFile.Replace(alt, standard); - } - - int baseLen = fromDir.Length; - if (!toFile.StartsWith(fromDir)) { return null; } - if (toFile.Length <= baseLen) { return null; } - var sep = toFile[baseLen]; - if (sep != Path.DirectorySeparatorChar) - { - return null; - } - return toFile.Substring(baseLen + 1); - } - - private async Task CreateZipFileAsync( - string zipName, string rootDir, string[] paths, - CancellationToken token) - { - long totalLength = paths.Aggregate(0L, (acc, elt) => acc + new FileInfo(elt).Length) + 1; - long read = 1; - - using (var zip = File.OpenWrite(zipName)) - { - using (var archive = new ZipArchive(zip, ZipArchiveMode.Create)) - { - foreach (var path in paths) - { - string archivedName = GetRelativePath(rootDir, path); - if (archivedName == null) - { - Debug.LogWarning($"Ignoring {path} not under {rootDir}"); - continue; - } - ZipArchiveEntry entry = archive.CreateEntry(archivedName); - using (Stream writer = entry.Open()) - { - using (var reader = new StreamWithReadProgress(path)) - { - var task = reader.CopyToAsync(writer, 0x1_0000, token); - while (!task.IsCompleted) - { - long prev = reader.TotalRead; - await Awaiters.NextFrame; - read += reader.TotalRead - prev; - SetUploadProgress(UploadStep.ZipElements, read / (double)(totalLength)); - } - await task; - } - } - } - } - } - } - - private async Task<(string, long)> UploadCurrentSketchSketchfabAsync( - CancellationToken token, string tempUploadDir, bool _) - { - DiskSceneFileInfo fileInfo = GetWritableFile(); - - SetUploadProgress(UploadStep.CreateGltf, 0); - // Do the glTF straight away as it relies on the meshes, not the stroke descriptions. - string gltfFile = Path.Combine(tempUploadDir, kGltfName); - var exportResults = await OverlayManager.m_Instance.RunInCompositorAsync( - OverlayType.Export, fadeDuration: 0.5f, - action: () => new ExportGlTF().ExportBrushStrokes( - gltfFile, - AxisConvention.kGltf2, binary: false, doExtras: false, - includeLocalMediaContent: true, gltfVersion: 2, - // Sketchfab doesn't support absolute texture URIs - selfContained: true)); - if (!exportResults.success) - { - throw new VrAssetServiceException("Internal error creating upload data."); - } - - // Construct options to set the background color to the current environment's clear color. - Color bgColor = SceneSettings.m_Instance.CurrentEnvironment.m_RenderSettings.m_ClearColor; - SketchfabService.Options options = new SketchfabService.Options(); - options.SetBackgroundColor(bgColor); - - // TODO(b/146892613): we're not uploading this at the moment. Should we be? - // If we don't, we can probably remove this step...? - SetUploadProgress(UploadStep.CreateTilt, 0); - await CreateTiltForUploadAsync(fileInfo); - token.ThrowIfCancellationRequested(); - - // Create a copy of the .tilt file in tempUploadDir. - string tempTiltPath = Path.Combine(tempUploadDir, "sketch.tilt"); - File.Copy(fileInfo.FullPath, tempTiltPath); - - // Collect files into a .zip file, including the .tilt file. - string zipName = Path.Combine(tempUploadDir, "archive.zip"); - var filesToZip = exportResults.exportedFiles.ToList().Append(tempTiltPath); - await CreateZipFileAsync(zipName, tempUploadDir, filesToZip.ToArray(), token); - var uploadLength = new FileInfo(zipName).Length; - - var service = new SketchfabService(App.SketchfabIdentity); - var progress = new Progress(d => SetUploadProgress(UploadStep.UploadElements, d)); - var response = await service.CreateModel( - fileInfo.HumanName, zipName, progress, token, options, tempUploadDir); - // TODO(b/146892613): return the UID and stick it into the .tilt file? - // Or do we not care since we aren't recording provenance and remixing - - // TODO(b/146892613): figure out this flow - // response.uri is not very useful; it is an API uri that gives you json of asset details. - // Also, the 3d-models URI might show that the asset is still processing. We can poll their - // API and find out when it's done and pop up the window then? - string uri = $"{SketchfabService.kModelLandingPage}{response.uid}"; - return (uri, uploadLength); - } - - /// Helper for UploadCurrentSketchXxxAsync - /// Writes the sketch to the passed fileInfo and returns a sketch thumbnail. - private async Task CreateTiltForUploadAsync(DiskSceneFileInfo fileInfo) - { - // Create and save snapshot. - SetUploadProgress(UploadStep.CreateTilt, 0); - SketchControlsScript.m_Instance.GenerateReplacementSaveIcon(); - SketchSnapshot snapshot = await SaveLoadScript.m_Instance.CreateSnapshotWithIconsAsync(); - snapshot.AssetId = fileInfo.AssetId; // FileInfo and snapshot must match - await SaveLoadScript.m_Instance.SaveSnapshot(fileInfo, snapshot: snapshot); - if (!File.Exists(fileInfo.FullPath)) - { - string exceptionMessage = "Internal error uploading .tilt."; - if (SaveLoadScript.m_Instance.LastWriteSnapshotError != null) - { - exceptionMessage += " Error: " + SaveLoadScript.m_Instance.LastWriteSnapshotError; - } - else - { - exceptionMessage += " No error message"; - } - - throw new VrAssetServiceException(exceptionMessage); - } - - byte[] thumbnail = SaveLoadScript.m_Instance.GetLastThumbnailBytes(); - if (thumbnail == null) - { - thumbnail = FileSketchSet.ReadThumbnail(fileInfo) ?? new byte[0]; - } - - return thumbnail; - } - - public AssetGetter GetAsset(string assetId, VrAssetFormat type, string reason) - { - string uri; - if (assetId.ToLower().StartsWith("https%3a%2f%2f") || assetId.ToLower().StartsWith("http%3a%2f%2f")) - { - uri = UnityWebRequest.UnEscapeURL(assetId); - } - else - { - uri = String.Format("{0}{1}/{2}?key={3}", ApiHost, kListAssetsUri, assetId, kPolyApiKey); - } - return new AssetGetter(uri, assetId, type, reason); - } - - public AssetLister ListAssets(SketchSetType type) - { - string filter = null; - string errorMessage = null; - switch (type) - { - case SketchSetType.Liked: - if (!App.GoogleIdentity.LoggedIn) - { - return null; - } - filter = $"{kUserLikesUri}?format=TILT&orderBy=LIKED_TIME&key={kPolyApiKey}"; - errorMessage = "Failed to access your liked sketches."; - break; - case SketchSetType.Curated: - if (string.IsNullOrEmpty(kPolyApiKey)) - { - return null; - } - filter = $"{kListAssetsUri}?format=TILT&curated=true&orderBy=NEWEST&key={kPolyApiKey}"; - errorMessage = "Failed to access featured sketches."; - break; - } - - string uri = $"{ApiHost}{filter}&pageSize={m_AssetsPerPage}"; - return new AssetLister(uri, errorMessage); - } - - // Get a specific sketch and insert it into the listed sketches at the specified index. - public IEnumerator InsertSketchInfo( - string assetId, int index, List infos) - { - string uri = String.Format("{0}{1}/{2}?key={3}", ApiHost, kListAssetsUri, assetId, kPolyApiKey); - WebRequest request = new WebRequest(uri, App.GoogleIdentity, UnityWebRequest.kHttpVerbGET); - using (var cr = request.SendAsync().AsIeNull()) - { - while (!request.Done) - { - try - { - cr.MoveNext(); - } - catch (VrAssetServiceException e) - { - Debug.LogException(e); - Debug.LogError("Failed to fetch sketch " + assetId); - yield break; - } - yield return cr.Current; - } - } - - Future f = new Future(() => JObject.Parse(request.Result)); - JObject json; - while (!f.TryGetResult(out json)) { yield return null; } - infos.Insert(index, new PolySceneFileInfo(json.Root)); - } - - public AssetLister ListAssets(PolySetType type) - { - string uri = null; - switch (type) - { - case PolySetType.Liked: - uri = $"{ApiHost}{kUserLikesUri}?format=GLTF2&orderBy=LIKED_TIME&pageSize={m_AssetsPerPage}"; - break; - case PolySetType.User: - uri = $"{ApiHost}{kUserAssetsUri}?format=GLTF2&orderBy=NEWEST&pageSize={m_AssetsPerPage}"; - break; - case PolySetType.Featured: - uri = $"{ApiHost}{kListAssetsUri}?key={kPolyApiKey}" + - $"&format=GLTF2&curated=true&orderBy=NEWEST&pageSize={m_AssetsPerPage}"; - break; - } - return new AssetLister(uri, "Failed to connect to Poly."); - } - - // Download a tilt file to a temporary file and load it - public IEnumerator LoadTiltFile(string id) - { - string path = Path.GetTempFileName(); - string uri = String.Format("{0}{1}/{2}?key={3}", ApiHost, kListAssetsUri, id, kPolyApiKey); - WebRequest request = new WebRequest(uri, App.GoogleIdentity, UnityWebRequest.kHttpVerbGET); - using (var cr = request.SendAsync().AsIeNull()) - { - while (!request.Done) - { - try - { - cr.MoveNext(); - } - catch (VrAssetServiceException) - { - yield break; - } - yield return cr.Current; - } - } - JObject json = JObject.Parse(request.Result); - var info = new PolySceneFileInfo(json); - using (UnityWebRequest www = UnityWebRequest.Get(info.TiltFileUrl)) - { - yield return www.SendWebRequest(); - while (!www.downloadHandler.isDone) { yield return null; } - FileStream stream = File.Create(path); - byte[] data = www.downloadHandler.data; - stream.Write(data, 0, data.Length); - stream.Close(); - } - - SketchControlsScript.m_Instance.IssueGlobalCommand( - SketchControlsScript.GlobalCommands.LoadNamedFile, sParam: path); - File.Delete(path); - } - } - -} // namespace TiltBrush +// Copyright 2020 The Tilt Brush Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// 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; +using System.Collections.Generic; +using System.IO; +using System.IO.Compression; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Newtonsoft.Json.Linq; +using Org.OpenAPITools.Api; +using UnityEngine; +using UnityEngine.Networking; + +namespace TiltBrush +{ + + /// Back-end for cloud upload + /// These values might be serialized into prefabs; do not change them! + /// Make serializable so they don't get mangled by obfuscation. + [Serializable] + public enum Cloud + { + None = 0, + Google = 1, + Sketchfab = 2, + Icosa = 3, + } + + [Serializable] + public enum VrAssetFormat + { + Unknown, + TILT, + GLTF, + GLTF2, + } + + public class VrAssetService : MonoBehaviour + { + // Constants + + const string kDefaultName = "sketch"; + + private const string kListAssetsUri = "/assets"; + private const string kUserAssetsUri = "/users/me/assets"; + private const string kUserLikesUri = "/users/me/likedassets"; + + public const string kCreativeCommonsLicense = "CREATIVE_COMMONS_BY"; + + // Icosa API used by Open Brush. + // If Icosa doesn't support this version, don't try to talk to Icosa and prompt the user to upgrade. + private const string kIcosaApiVersion = "v1"; + + /// Change-of-basis transform + public static readonly TrTransform kIcosaFromUnity; + + private static Dictionary kGltfMimetypes = new Dictionary + { + { ".gltf", "model/gltf+json" }, + { ".bin", "application/octet-stream" }, + { ".glsl", "text/plain" }, + { ".bmp", "image/bmp" }, + { ".jpeg", "image/jpeg" }, + { ".jpg", "image/jpeg" }, + { ".png", "image/png" }, + { ".tilt", "application/octet-stream" } + }; + + // For progress reporting + private enum UploadStep + { + CreateGltf, + CreateTilt, + ZipElements, + UploadElements, + UpdateAssetData, + Done + } + + // These are progress values at the start of each step. + // TODO(b/146892613): have a different set for Icosa vs Sketchfab? + private static double[] kProgressSteps = + { + 0.01, // UploadStep.CreateGltf -- progress > 0 means we have begun + 0.25, // UploadStep.CreateTilt + 0.3, // UploadStep.ZipElements + 0.5, // UploadStep.UploadElements + 0.95, // UploadStep.UpdateAssetData + 1, // UploadStep.Done + 1 // + }; + + // Classes and types + + class StreamWithReadProgress : WrappedStream + { + public int TotalRead { get; private set; } + public StreamWithReadProgress(string filename) + { + SetWrapped(File.OpenRead(filename), ownsStream: true); + } + public override int Read(byte[] buffer, int offset, int count) + { + var amountRead = base.Read(buffer, offset, count); + TotalRead += amountRead; + return amountRead; + } + public override int ReadByte() + { + var amountRead = base.ReadByte(); + TotalRead += amountRead; + return amountRead; + } + } + + /// A bag of information about a pending upload + class UploadInfo : IProgress + { + // Only one of sourceFile or sourceData is valid + public readonly FileInfo m_sourceFile; + public readonly byte[] m_sourceData; + public readonly string m_remoteName; + public readonly long m_length; + public string m_elementId; + public double m_uploadPercent = 0; + + public UploadInfo(string sourceFile, string remoteName) + { + m_sourceFile = new FileInfo(sourceFile); + m_remoteName = remoteName; + m_length = m_sourceFile.Length; + } + + public UploadInfo(byte[] data, string remoteName) + { + m_sourceData = data; + m_remoteName = remoteName; + m_length = data.Length; + } + + public void SetUploaded(string elementId) + { + m_elementId = elementId; + } + + /// Allocates and returns a new Stream. + /// Caller is responsible for disposing of it. + public Stream OpenStream() + { + if (m_sourceData != null) + { + return new MemoryStream(m_sourceData); + } + else + { + return m_sourceFile.OpenRead(); + } + } + + void IProgress.Report(double value) + { + m_uploadPercent = value; + } + } + + /// Creates and then cleans up a uniquely-named temporary directory + class TemporaryUploadDirectory : IDisposable + { + public string Value { get; } + + public TemporaryUploadDirectory() + { +#if UNITY_EDITOR + if (App.Config && App.Config.m_DebugUpload) + { + // Delay deleting the directory until the next upload + string dirName = Path.Combine(Application.temporaryCachePath, "Upload"); + if (Directory.Exists(dirName)) + { + try { Directory.Delete(dirName, true); } + catch (Exception e) { Debug.LogException(e); } + } + } +#endif + Value = FileUtils.GenerateNonexistentFilename( + Application.temporaryCachePath, "Upload", ""); + string failureMessage = $"Can't create upload directory: {Value}"; + bool dirCreated = FileUtils.InitializeDirectoryWithUserError(Value, failureMessage); + if (!dirCreated) + { + throw new VrAssetServiceException(failureMessage); + } + } + + public void Dispose() + { +#if UNITY_EDITOR + if (App.Config && App.Config.m_DebugUpload) + { + // Delay deleting the directory until the next upload + return; + } +#endif + if (Directory.Exists(Value)) + { + Directory.Delete(Value, true); + } + } + } + + // Static API + + public static VrAssetService m_Instance; + + // Currently this always returns the standard API host when running unit tests + public string IcosaApiRoot + { + get + { + string cfg = App.UserConfig?.Sharing.IcosaApiRoot; + if (!string.IsNullOrEmpty(cfg)) { return cfg; } + return "https://api.icosa.gallery/v1"; + } + } + + public string IcosaHomePage + { + get + { + string cfg = App.UserConfig.Sharing.IcosaHomePage; + if (!string.IsNullOrEmpty(cfg)) { return cfg; } + return "https://icosa.gallery"; + } + } + + private string IcosaUploadPage => $"{IcosaHomePage}/uploads"; + + /// Returns true if Icosa would accept a PATCH of the specified asset + /// from the specified user. + /// + /// Pass: + /// type - + /// Where you found the assetId. Necessary because of some shortcuts + /// taken by the implementation. + /// userId - Icosa user id of the currently-logged-in OAuth user. Get it + /// with GetAccountIdAsync(). + public static async Task IsMutableAssetIdAsync( + FileInfoType type, string assetId, string userId, string apiHost) + { + if (assetId == null) { return false; } + // There are too many assumptions here -- for both cloud and disk, the logic + // should be "is it owned by me and unpublished? then it's mutable" + if (type == FileInfoType.Cloud) + { + // Assumption: cloud files are immutable. + // You can't "Like" an unpublished asset; and published assets are immutable. + return false; + } + else if (type == FileInfoType.Disk) + { + // Assumption: this asset is mutable because it's unlikely for a cloud-based .tilt + // to be in the user's Sketches/ folder. Local sketches always become un-published + // and mutable assets when uploaded (remember, publishing makes a copy). + // If someone grabbed a .tilt from their Icosa asset cache and put it in Sketches/ + // that would break this assumption and I'm not sure what would happen. + if (userId == null) { return false; } + // It's mutable, but check whether it's mutable by _us_. + try + { + // The null == null case is handled earlier + WebRequest request = new WebRequest( + $"{apiHost}{kListAssetsUri}/{assetId}", + App.Instance.IcosaToken, UnityWebRequest.kHttpVerbGET); + return (await request.SendAsync()).JObject?["accountId"].ToString() == userId; + } + catch (VrAssetServiceException) + { + return false; + } + } + else + { + throw new InvalidOperationException($"Unknown FileInfoType {type}"); + } + } + + // Instance API + + static VrAssetService() + { + Matrix4x4 polyFromUnity = AxisConvention.GetFromUnity(AxisConvention.kGltfAccordingToIcosa); + + // Provably non-lossy: the mat4 is purely TRS, and the S is uniform + kIcosaFromUnity = TrTransform.FromMatrix4x4(polyFromUnity); + } + + // Instance API + + [SerializeField] private int m_AssetsPerPage; + [SerializeField] public float m_SketchbookRefreshInterval; + public bool m_UseLocalFeaturedSketches = false; + + private float m_UploadProgress; + private bool m_LastUploadFailed; + private string m_LastUploadErrorMessage; + private string m_LastUploadErrorDetails; + private bool m_UserCanceledLastUpload; + private string m_LastUploadCompleteUrl; + TaskAndCts<(string url, long bytes)> m_UploadTask = null; + private string m_IcosaAccountId; + + private enum IcosaStatus + { + Ok, + Disabled, + NoConnection + } + private IcosaStatus m_IcosaStatus; + + public bool Available => m_IcosaStatus == IcosaStatus.Ok; + + public bool NoConnection => m_IcosaStatus == IcosaStatus.NoConnection; + + public float UploadProgress => m_UploadProgress; + + public bool LastUploadFailed + { + get { return m_LastUploadFailed; } + } + + public string LastUploadErrorMessage + { + get { return m_LastUploadErrorMessage; } + } + + public string LastUploadErrorDetails + { + get { return m_LastUploadErrorDetails; } + } + + public bool UserCanceledLastUpload + { + get { return m_UserCanceledLastUpload; } + } + + public string LastUploadCompleteUrl + { + get { return m_LastUploadCompleteUrl; } + } + + // Cannot be an UploadProgress setter because the getter's type is different. + // pct is how much of that step has been completed. + private void SetUploadProgress(UploadStep step, double pct) + { + var step0 = (float)kProgressSteps[Mathf.Min(kProgressSteps.Length - 1, (int)step)]; + var step1 = (float)kProgressSteps[Mathf.Min(kProgressSteps.Length - 1, (int)step + 1)]; + m_UploadProgress = Mathf.Lerp(step0, step1, (float)pct); + } + + void Awake() + { + m_Instance = this; + } + + void Start() + { + // If auto profiling is enabled, disable automatic Icosa downloading. + if (!App.UserConfig.Profiling.AutoProfile) + { + VerifyIcosaConnectionAndCheckApiVersionAsync(); + } + else + { + m_IcosaStatus = IcosaStatus.Disabled; + } + } + + /// Consume the result of the previous upload (if any) + public void ConsumeUploadResults() + { + // Our UI interprets "progress >= 1.0" as "there are results and we must display them!" + // The UI should really be internally stateful, and only display these results when new results + // appear that haven't yet been shown to the user. The issue with this design is that there + // are other consumers of upload results. Thankfully, they are less important and don't + // care about progress; so the hack is that we only "consume" the progress. + if (m_UploadProgress >= 1) + { + m_UploadProgress = 0; + } + } + + /// If you try and upload a sketch while a sketch is already uploading, + /// the existing upload will be canceled. + public async Task UploadCurrentSketchAsync(Cloud backend, bool isDemoUpload) + { + // This function handles most of the setup and cleanup. + // The heavy lifting is split out into UploadCurrentSketchInternal. + + // Generic to all kinds of failures + void ReportFailure(string userFriendly, string fullMessage = "") + { + m_LastUploadFailed = true; + m_LastUploadErrorMessage = userFriendly; + m_LastUploadErrorDetails = fullMessage; + ControllerConsoleScript.m_Instance.AddNewLine(LastUploadErrorMessage, skipLog: true); + ControllerConsoleScript.m_Instance.AddNewLine(LastUploadErrorDetails, skipLog: true); + AudioManager.m_Instance.PlayUploadCanceledSound(InputManager.Wand.Transform.position); + } + + Debug.LogFormat("UploadCurrentSketch(demo: {0})", isDemoUpload); + + // Cancel previous upload coroutine if necessary. + if (m_UploadTask != null) + { + CancelUpload(); + if (await Task.WhenAny(m_UploadTask.Task, Task.Delay(TimeSpan.FromSeconds(5))) != + m_UploadTask.Task) + { + // Definitely a bug we should fix; make it noisy because otherwise it just looks + // like nothing is happening. + OutputWindowScript.Error("Timed out waiting for canceled upload"); + return; + } + } + + + m_LastUploadFailed = false; + m_LastUploadErrorMessage = ""; + m_LastUploadErrorDetails = ""; + m_UserCanceledLastUpload = false; + m_UploadProgress = 0.0f; + + using (var tempUploadDir = new TemporaryUploadDirectory()) + try + { + if (!isDemoUpload) + { + App.Instance.SetDesiredState(App.AppState.Uploading); + } + AudioManager.m_Instance.UploadLoop(true); + var timer = System.Diagnostics.Stopwatch.StartNew(); + m_UploadTask = new TaskAndCts<(string url, long bytes)>(); + + switch (backend) + { + case Cloud.Icosa: + m_UploadTask.Task = UploadCurrentSketchIcosaAsync(m_UploadTask.Token, tempUploadDir.Value, + isDemoUpload); + break; + case Cloud.Sketchfab: + m_UploadTask.Task = UploadCurrentSketchSketchfabAsync(m_UploadTask.Token, tempUploadDir.Value, + isDemoUpload); + break; + } + var (url, totalUploadLength) = await m_UploadTask.Task; + m_LastUploadCompleteUrl = url; + ControllerConsoleScript.m_Instance.AddNewLine("Upload succeeded!"); + AudioManager.m_Instance.PlayUploadCompleteSound(InputManager.Wand.Transform.position); + PanelManager.m_Instance.GetAdminPanel().ActivatePromoBorder(true); + // Don't auto-open the URL on mobile because it steals focus from the user. + if (!isDemoUpload && !App.Config.IsMobileHardware && m_LastUploadCompleteUrl != null) + { + // Can't pass a string param because this is also called from mobile GUI + SketchControlsScript.m_Instance.IssueGlobalCommand( + SketchControlsScript.GlobalCommands.ViewLastUpload); + } + } + catch (VrAssetServiceException exception) + { + // "Expected" failures (40x, 50x, etc) + Debug.LogWarning("UploadCurrentSketch external error"); + Debug.LogException(exception); + ReportFailure(exception.UserFriendly, exception.Message); + } + catch (OperationCanceledException) + { + m_UserCanceledLastUpload = true; + ReportFailure("Upload canceled."); + } + catch (Exception exception) + { + // Unexpected failures -- ie, bugs on our part + Debug.LogError("UploadCurrentSketch internal error"); + ReportFailure("Upload failed.", exception.Message); + throw; + } + finally + { + // Cleanup + if (App.CurrentState == App.AppState.Uploading) + { + App.Instance.SetDesiredState(App.AppState.Standard); + } + + m_UploadTask = null; + AudioManager.m_Instance.UploadLoop(false); + // This is how the upload popup knows we're complete + m_UploadProgress = 1.0f; + } + } + + /// Request to cancel the upload -- does not happen synchronously. + public void CancelUpload() + { + m_UploadTask?.Cancel(); + } + + private async void VerifyIcosaConnectionAndCheckApiVersionAsync() + { + m_IcosaStatus = await GetIcosaStatus(); + } + + private async Task GetIcosaStatus() + { + // UserConfig override + if (App.UserConfig.Flags.DisableIcosa) + { + return IcosaStatus.Disabled; + } + + try + { + // TODO need a do-nothing endpoint we can use for this + var api = new LoginApi(IcosaApiRoot); + var result = new Dictionary { { "version", "v1" } }; // TODO: get version from API + string version = result["version"]; + if (version == kIcosaApiVersion) + { + return IcosaStatus.Ok; + } + else + { + Debug.LogWarning($"Icosa requires API {version} > {kIcosaApiVersion}"); + return IcosaStatus.Disabled; + } + } + catch (VrAssetServiceException e) + { + Debug.LogWarning($"Error connecting to Icosa: {e}"); + return IcosaStatus.NoConnection; + } + catch (Exception e) + { + Debug.LogError($"Internal error connecting to Icosa: {e}"); + return IcosaStatus.NoConnection; + } + } + + /// Returns a writable SceneFileInfo + private DiskSceneFileInfo GetWritableFile() + { + // hermetic gltf files currently don't work with AccessLevel.PRIVATE + SceneFileInfo currentFileInfo = SaveLoadScript.m_Instance.SceneFile; + + DiskSceneFileInfo fileInfo; + if (currentFileInfo.Valid) + { + if (currentFileInfo is DiskSceneFileInfo) + { + fileInfo = (DiskSceneFileInfo)currentFileInfo; + } + else + { + // This is a cloud sketch not saved before + fileInfo = SaveLoadScript.m_Instance.GetNewNameSceneFileInfo(); + } + } + else + { + // Save as a new file + fileInfo = SaveLoadScript.m_Instance.GetNewNameSceneFileInfo(); + } + return fileInfo; + } + + /// Returns a relative path R such that Join(fromDir, R) refers to toFile, or null on error. + /// Does not handle ".." paths. + public static string GetRelativePath(string fromDir, string toFile) + { + // Normalize paths so we can use plain string compares + var alt = Path.AltDirectorySeparatorChar; + var standard = Path.DirectorySeparatorChar; + if (alt != standard) + { + fromDir = fromDir.Replace(alt, standard); + toFile = toFile.Replace(alt, standard); + } + + int baseLen = fromDir.Length; + if (!toFile.StartsWith(fromDir)) { return null; } + if (toFile.Length <= baseLen) { return null; } + var sep = toFile[baseLen]; + if (sep != Path.DirectorySeparatorChar) + { + return null; + } + return toFile.Substring(baseLen + 1); + } + + private async Task CreateZipFileAsync( + string zipName, string rootDir, string[] paths, + CancellationToken token) + { + long totalLength = paths.Aggregate(0L, (acc, elt) => acc + new FileInfo(elt).Length) + 1; + long read = 1; + + using (var zip = File.OpenWrite(zipName)) + { + using (var archive = new ZipArchive(zip, ZipArchiveMode.Create)) + { + foreach (var path in paths) + { + string archivedName = GetRelativePath(rootDir, path); + if (archivedName == null) + { + Debug.LogWarning($"Ignoring {path} not under {rootDir}"); + continue; + } + ZipArchiveEntry entry = archive.CreateEntry(archivedName); + using (Stream writer = entry.Open()) + { + using (var reader = new StreamWithReadProgress(path)) + { + var task = reader.CopyToAsync(writer, 0x1_0000, token); + while (!task.IsCompleted) + { + long prev = reader.TotalRead; + await Awaiters.NextFrame; + read += reader.TotalRead - prev; + SetUploadProgress(UploadStep.ZipElements, read / (double)(totalLength)); + } + await task; + } + } + } + } + } + } + + // TODO: Refactor. This is largely the same as UploadCurrentSketchSketchFabAsync aside from a few url changes and the response. + private async Task<(string, long)> UploadCurrentSketchIcosaAsync( + CancellationToken token, string tempUploadDir, bool _) + { + DiskSceneFileInfo fileInfo = GetWritableFile(); + + var currentScene = SaveLoadScript.m_Instance.SceneFile; + string uploadName = currentScene.Valid ? currentScene.HumanName : kDefaultName; + string gltfUploadName = $"{uploadName}.gltf"; + + SetUploadProgress(UploadStep.CreateGltf, 0); + // Do the glTF straight away as it relies on the meshes, not the stroke descriptions. + string gltfFile = Path.Combine(tempUploadDir, gltfUploadName); + var exportResults = await OverlayManager.m_Instance.RunInCompositorAsync( + OverlayType.Export, fadeDuration: 0.5f, + action: () => new ExportGlTF().ExportBrushStrokes( + gltfFile, + AxisConvention.kGltf2, binary: false, doExtras: true, + includeLocalMediaContent: true, gltfVersion: 2, + selfContained: true)); + if (!exportResults.success) + { + throw new VrAssetServiceException("Internal error creating upload data."); + } + + // Construct options to set the background color to the current environment's clear color. + Color bgColor = SceneSettings.m_Instance.CurrentEnvironment.m_RenderSettings.m_ClearColor; + IcosaService.Options options = null; + // options.SetBackgroundColor(bgColor); + + // TODO(b/146892613): we're not uploading this at the moment. Should we be? + // If we don't, we can probably remove this step...? + SetUploadProgress(UploadStep.CreateTilt, 0); + var thumbnail = await CreateTiltForUploadAsync(fileInfo); + token.ThrowIfCancellationRequested(); + + // Create a copy of the .tilt file in tempUploadDir. + string tempTiltPath = Path.Combine(tempUploadDir, $"{uploadName}.tilt"); + File.Copy(fileInfo.FullPath, tempTiltPath); + + // Save thumbnail as a png to temp path + string tempThumbnailPath = Path.Combine(tempUploadDir, "thumbnail.png"); + File.WriteAllBytes(tempThumbnailPath, thumbnail); + + // Collect files into a .zip file, including the .tilt file and thumbnail + string zipName = Path.Combine(tempUploadDir, "archive.zip"); + var filesToZip = exportResults.exportedFiles.ToList().Append(tempTiltPath).Append(tempThumbnailPath); + await CreateZipFileAsync(zipName, tempUploadDir, filesToZip.ToArray(), token); + + var service = new IcosaService(App.Instance.IcosaToken); + var progress = new Progress(d => SetUploadProgress(UploadStep.UploadElements, d)); + IcosaService.CreateResponse response = await service.CreateModel( + zipName, progress, token, options, tempUploadDir); + // TODO(b/146892613): return the UID and stick it into the .tilt file? + // Or do we not care since we aren't recording provenance and remixing + + // TODO(b/146892613): figure out this flow + // response.uri is not very useful; it is an API uri that gives you json of asset details. + // Also, the 3d-models URI might show that the asset is still processing. We can poll their + // API and find out when it's done and pop up the window then? + string uri = $"{response.edit_url}"; + return (uri, 0); + } + + private async Task<(string, long)> UploadCurrentSketchSketchfabAsync( + CancellationToken token, string tempUploadDir, bool _) + { + DiskSceneFileInfo fileInfo = GetWritableFile(); + + SetUploadProgress(UploadStep.CreateGltf, 0); + // Do the glTF straight away as it relies on the meshes, not the stroke descriptions. + string gltfFile = Path.Combine(tempUploadDir, $"{kDefaultName}.gltf"); + var exportResults = await OverlayManager.m_Instance.RunInCompositorAsync( + OverlayType.Export, fadeDuration: 0.5f, + action: () => new ExportGlTF().ExportBrushStrokes( + gltfFile, + AxisConvention.kGltf2, binary: false, doExtras: false, + includeLocalMediaContent: true, gltfVersion: 2, + // Sketchfab doesn't support absolute texture URIs + selfContained: true)); + if (!exportResults.success) + { + throw new VrAssetServiceException("Internal error creating upload data."); + } + + // Construct options to set the background color to the current environment's clear color. + Color bgColor = SceneSettings.m_Instance.CurrentEnvironment.m_RenderSettings.m_ClearColor; + SketchfabService.Options options = new SketchfabService.Options(); + options.SetBackgroundColor(bgColor); + + // TODO(b/146892613): we're not uploading this at the moment. Should we be? + // If we don't, we can probably remove this step...? + SetUploadProgress(UploadStep.CreateTilt, 0); + await CreateTiltForUploadAsync(fileInfo); + token.ThrowIfCancellationRequested(); + + // Create a copy of the .tilt file in tempUploadDir. + string tempTiltPath = Path.Combine(tempUploadDir, "sketch.tilt"); + File.Copy(fileInfo.FullPath, tempTiltPath); + + // Collect files into a .zip file, including the .tilt file. + string zipName = Path.Combine(tempUploadDir, "archive.zip"); + var filesToZip = exportResults.exportedFiles.ToList().Append(tempTiltPath); + await CreateZipFileAsync(zipName, tempUploadDir, filesToZip.ToArray(), token); + var uploadLength = new FileInfo(zipName).Length; + + var service = new SketchfabService(App.SketchfabIdentity); + var progress = new Progress(d => SetUploadProgress(UploadStep.UploadElements, d)); + var response = await service.CreateModel( + fileInfo.HumanName, zipName, progress, token, options, tempUploadDir); + // TODO(b/146892613): return the UID and stick it into the .tilt file? + // Or do we not care since we aren't recording provenance and remixing + + // TODO(b/146892613): figure out this flow + // response.uri is not very useful; it is an API uri that gives you json of asset details. + // Also, the 3d-models URI might show that the asset is still processing. We can poll their + // API and find out when it's done and pop up the window then? + string uri = $"{SketchfabService.kModelLandingPage}{response.uid}"; + return (uri, uploadLength); + } + + /// Helper for UploadCurrentSketchXxxAsync + /// Writes the sketch to the passed fileInfo and returns a sketch thumbnail. + private async Task CreateTiltForUploadAsync(DiskSceneFileInfo fileInfo) + { + // Create and save snapshot. + SetUploadProgress(UploadStep.CreateTilt, 0); + SketchControlsScript.m_Instance.GenerateReplacementSaveIcon(); + SketchSnapshot snapshot = await SaveLoadScript.m_Instance.CreateSnapshotWithIconsAsync(); + snapshot.AssetId = fileInfo.AssetId; // FileInfo and snapshot must match + await SaveLoadScript.m_Instance.SaveSnapshot(fileInfo, snapshot: snapshot); + if (!File.Exists(fileInfo.FullPath)) + { + string exceptionMessage = "Internal error uploading .tilt."; + if (SaveLoadScript.m_Instance.LastWriteSnapshotError != null) + { + exceptionMessage += " Error: " + SaveLoadScript.m_Instance.LastWriteSnapshotError; + } + else + { + exceptionMessage += " No error message"; + } + + throw new VrAssetServiceException(exceptionMessage); + } + + byte[] thumbnail = SaveLoadScript.m_Instance.GetLastThumbnailBytes(); + if (thumbnail == null) + { + thumbnail = FileSketchSet.ReadThumbnail(fileInfo) ?? new byte[0]; + } + + return thumbnail; + } + + public AssetGetter GetAsset(string assetId, VrAssetFormat type, string reason) + { + string uri; + if (assetId.ToLower().StartsWith("https%3a%2f%2f") || assetId.ToLower().StartsWith("http%3a%2f%2f")) + { + uri = UnityWebRequest.UnEscapeURL(assetId); + } + else + { + uri = String.Format("{0}{1}/{2}", IcosaApiRoot, kListAssetsUri, assetId); + } + return new AssetGetter(uri, assetId, type, reason); + } + + private string CombineQueryParams(string uriPath, string additionalParams) + { + string separator = uriPath.Contains("?") ? "&" : "?"; + return $"{uriPath}{separator}{additionalParams}"; + } + + public AssetLister ListAssets(SketchSetType type) + { + string filteredUriPath = null; + string errorMessage = null; + switch (type) + { + // TODO Add User sketches + // TODO Allow non-CC-BY sketches to be loaded as read-only + case SketchSetType.Liked: + if (!App.IcosaIsLoggedIn) + { + return null; + } + filteredUriPath = CombineQueryParams(kUserLikesUri, "format=TILT&orderBy=LIKED_TIME&license=CREATIVE_COMMONS_BY"); + errorMessage = "Failed to access your liked sketches."; + break; + case SketchSetType.Curated: + // Old way - newest curated + // filteredUriPath = CombineQueryParams(kListAssetsUri, "format=TILT&curated=true&orderBy=NEWEST"); + // For now try just sorting by "best" + filteredUriPath = CombineQueryParams(kListAssetsUri, "format=TILT&orderBy=BEST&license=CREATIVE_COMMONS_BY"); + errorMessage = "Failed to access featured sketches."; + break; + } + + string uri = $"{IcosaApiRoot}{filteredUriPath}&pageSize={m_AssetsPerPage}"; + return new AssetLister(uri, errorMessage); + } + + // Get a specific sketch and insert it into the listed sketches at the specified index. + public IEnumerator InsertSketchInfo( + string assetId, int index, List infos) + { + string uri = String.Format("{0}{1}/{2}", IcosaApiRoot, kListAssetsUri, assetId); + WebRequest request = new WebRequest(uri, App.Instance.IcosaToken, UnityWebRequest.kHttpVerbGET); + using (var cr = request.SendAsync().AsIeNull()) + { + while (!request.Done) + { + try + { + cr.MoveNext(); + } + catch (VrAssetServiceException e) + { + Debug.LogException(e); + Debug.LogError("Failed to fetch sketch " + assetId); + yield break; + } + yield return cr.Current; + } + } + + Future f = new Future(() => JObject.Parse(request.Result)); + JObject json; + while (!f.TryGetResult(out json)) { yield return null; } + infos.Insert(index, new IcosaSceneFileInfo(json.Root)); + } + + public AssetLister ListAssets(IcosaSetType type) + { + string uri = IcosaApiRoot; + + switch (type) + { + case IcosaSetType.Liked: + // TODO Filter out non-remixable assets + // uri += $"{kUserLikesUri}?orderBy=LIKED_TIME&license=CREATIVE_COMMONS_BY"; + uri += $"{kUserLikesUri}?orderBy=LIKED_TIME"; + break; + case IcosaSetType.User: + uri += $"{kUserAssetsUri}?orderBy=NEWEST"; + break; + case IcosaSetType.Featured: + // Old way - newest curated + // uri += $"{kListAssetsUri}" + $"?curated=true&orderBy=NEWEST"; + // For now try just sorting by "best" + uri += $"{kListAssetsUri}" + $"?orderBy=BEST&license=CREATIVE_COMMONS_BY"; + // Something like orderBy=TRENDING would be good - BEST but weighted by recency + break; + } + uri += $"&format=GLTF2&pageSize={m_AssetsPerPage}"; + return new AssetLister(uri, errorMessage: "Failed to connect to Icosa."); + } + + // Download a tilt file to a temporary file and load it + public IEnumerator LoadTiltFile(string id) + { + string path = Path.GetTempFileName(); + string uri = String.Format("{0}{1}/{2}", IcosaApiRoot, kListAssetsUri, id); + WebRequest request = new WebRequest(uri, App.Instance.IcosaToken, UnityWebRequest.kHttpVerbGET); + using (var cr = request.SendAsync().AsIeNull()) + { + while (!request.Done) + { + try + { + cr.MoveNext(); + } + catch (VrAssetServiceException) + { + yield break; + } + yield return cr.Current; + } + } + JObject json = JObject.Parse(request.Result); + var info = new IcosaSceneFileInfo(json); + using (UnityWebRequest www = UnityWebRequest.Get(info.TiltFileUrl)) + { + yield return www.SendWebRequest(); + while (!www.downloadHandler.isDone) { yield return null; } + FileStream stream = File.Create(path); + byte[] data = www.downloadHandler.data; + stream.Write(data, 0, data.Length); + stream.Close(); + } + + SketchControlsScript.m_Instance.IssueGlobalCommand( + SketchControlsScript.GlobalCommands.LoadNamedFile, sParam: path); + File.Delete(path); + } + } + +} // namespace TiltBrush diff --git a/Assets/Scripts/Sharing/WebRequest.cs b/Assets/Scripts/Sharing/WebRequest.cs index 54e116a297..f9f43450c7 100644 --- a/Assets/Scripts/Sharing/WebRequest.cs +++ b/Assets/Scripts/Sharing/WebRequest.cs @@ -221,16 +221,12 @@ public static string RedactUriForError(string uriString) #endif } - /// Convenience method - public static Task GetAsync(string uri) - { - return new WebRequest(uri, App.GoogleIdentity, UnityWebRequest.kHttpVerbGET) - .SendAsync(); - } - private string m_Uri; private string m_Method; + private OAuth2Identity m_Identity; + private string m_LoginToken; + private byte[] m_Result = null; private int m_UploadedBytes = 0; private float? m_PreUploadProgress = null; @@ -302,6 +298,24 @@ public WebRequest(string uri, OAuth2Identity identity, m_Identity = identity; } + // identity may be null, in which case no authentication takes place + public WebRequest(string uri, string loginToken = null, + string method = UnityWebRequest.kHttpVerbGET, bool compress = false) + { + if (string.IsNullOrEmpty(uri)) + { + throw new ArgumentException("uri"); + } + if (!kEnableHttpCompression) + { + compress = false; + } + m_Method = method; + m_Compressed = compress; + m_Uri = uri; + m_LoginToken = loginToken; + } + /// Sends a multipart form that includes a parameter with data that comes from a stream. /// This method takes ownership of the stream and guarantees that it will be closed. /// Pass: @@ -438,7 +452,11 @@ public async Task SendAsync( } www.downloadHandler = new DownloadHandlerBuffer(); - if (m_Identity != null) + if (m_LoginToken != null) + { + www.SetRequestHeader("Authorization", $"bearer {m_LoginToken}"); + } + else if (m_Identity != null) { await m_Identity.Authenticate(www); } @@ -555,7 +573,14 @@ async void DelayedDispose(IDisposable id) // authorization has been revoked, so just log out here. if (IsAuthError(www.responseCode)) { - m_Identity.Logout(); + if (m_LoginToken != null) + { + App.Instance.LogoutIcosa(); + } + else if (m_Identity != null) + { + m_Identity.Logout(); + } throw new VrAssetServiceException("Not authorized for login. Automatically logged out.", RedactUriForError(m_Uri)); } diff --git a/Assets/Scripts/SketchControlsScript.cs b/Assets/Scripts/SketchControlsScript.cs index 4577277bec..9de731847a 100644 --- a/Assets/Scripts/SketchControlsScript.cs +++ b/Assets/Scripts/SketchControlsScript.cs @@ -1,5191 +1,5226 @@ -// Copyright 2020 The Tilt Brush Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// 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; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using TiltBrush.Layers; -using UnityEngine; -using UnityEngine.InputSystem; -using SymmetryMode = TiltBrush.PointerManager.SymmetryMode; - -namespace TiltBrush -{ - - public class SketchControlsScript : MonoBehaviour - { - public const string kRemoveHeadsetFyi = "Remove headset to view."; - const string kTiltBrushGalleryUrl = "https://poly.google.com/tiltbrush"; - const string kBlocksGalleryUrl = "https://poly.google.com/blocks"; - const string kPolyMainPageUri = "https://poly.google.com"; - - static public SketchControlsScript m_Instance; - static bool sm_enableGrabHaptics = true; - - // ------------------------------------------------------------ - // Constants and types - // ------------------------------------------------------------ - - public enum GlobalCommands - { - Null, - Save, - SaveNew, - Load, - NewSketch, - StraightEdge, - AutoOrient, - Undo, - Redo, - Tiltasaurus, - LightingHdr, - AudioVisualization, - ResetAllPanels, - SketchOrigin, - SymmetryPlane, - MultiMirror, - ViewOnly, - SaveGallery, - LightingLdr, - ShowSketchFolder, - About, - LoadNamedFile, // iParam1 : (optional) - send through a LoadSpeed as int - DropCam, - CuratedGallery, - Unused_UploadToCloud, - AnalyticsEnabled_Deprecated, - Credits, - LogOutOfGenericCloud, - DraftingVisibility, - DeleteSketch, - ShowWindowGUI, - MorePanels, - Cameras, - FAQ, - ExportRaw, - IRC, - YouTubeChat, - CameraOptions, - StencilsDisabled, - AdvancedTools, - FloatingPanelsMode, - StraightEdgeMeterDisplay, - Sketchbook, - ExportAll, - Lights, - SaveAndUpload, - StraightEdgeShape, - SaveOptions, - SketchbookMenu, - Disco, - ViewOnlineGallery, - CancelUpload, - AdvancedPanelsToggle, - Music, - Duplicate, - ToggleGroupStrokesAndWidgets, - SaveModel, - ViewPolyPage, - ViewPolyGallery, - ExportListed, - RenderCameraPath, - ToggleProfiling, - DoAutoProfile, - DoAutoProfileAndQuit, - ToggleSettings, - SummonMirror, - InvertSelection, - SelectAll, - FlipSelection, - ToggleBrushLab, - ReleaseNotes, - ToggleCameraPostEffects, - ToggleWatermark, - AccountInfo, - // LoadConfirmUnsaved -> LoadWaitOnDownload -> LoadConfirmComplex -> LoadComplexHigh -> Load - LoadConfirmUnsaved, - LoadConfirmComplex, - MemoryWarning, - MemoryExceeded, - ViewLastUpload, - LoadConfirmComplexHigh, - ShowTos, - ShowPrivacy, - ShowQuestSideLoading, - AshleysSketch, - UnloadReferenceImageCatalog, - SaveOnLocalChanges, - ToggleCameraPathVisuals, - ToggleCameraPathPreview, - DeleteCameraPath, - RecordCameraPath, - SelectCameraPath, - ToggleAutosimplification, - ShowGoogleDrive, - GoogleDriveSync_Folder, // iParam1: folder id as DriveSync.SyncedFolderType - GoogleDriveSync, - LoginToGenericCloud, // iParam1: Cloud enum - UploadToGenericCloud, // iParam1: Cloud enum - LoadWaitOnDownload, - SignOutConfirm, - ReadOnlyNotice, - ShowContribution, - - // Open Brush Reserved Enums 1000-1999 - LanguagePopup = 1000, - - RenameSketch = 5200, - OpenLayerOptionsPopup = 5201, - RenameLayer = 5202, - OpenDirectorChooserPopup = 5800, - OpenScriptsCommandsList = 6000, - OpenScriptsList = 6001, - OpenExampleScriptsList = 6002, - SymmetryTwoHanded = 6003, - OpenColorOptionsPopup = 7000, - ChangeSnapAngle = 8000, - MergeBrushStrokes = 10000, - RepaintOptions = 11500, - OpenNumericInputPopup = 12000 - } - - public enum ControlsType - { - KeyboardMouse, - SixDofControllers, - ViewingOnly - } - - public enum DraftingVisibilityOption - { - Visible, - Transparent, - Hidden - } - - public enum InputState - { - Standard, - Pan, - Rotation, - HeadLock, - ControllerLock, - PushPull, - BrushSize, - Save, - Load, - Num - } - - public enum LoadSpeed - { - Normal = -1, - Quick = 1, - } - - const float kControlPointHistoryMaxTime = 0.1f; - - class GazeResult - { - public bool m_HitWithGaze; - public bool m_HitWithController; - // ReSharper disable once NotAccessedField.Local - public bool m_WithinView; - public float m_ControllerDistance; - public Vector3 m_GazePosition; - public Vector3 m_ControllerPosition; - public InputManager.ControllerName m_ControllerName; - } - - class GrabWidgetControllerInfo - { - public InputManager.ControllerName m_Name; - /// Transform of controller at the time the grab started - public TrTransform m_BaseControllerXf; - /// "local" transform of widget (relative to controller), at the time the grab started. - /// The widget isn't parented to the controller, but if it were, this would be its transform. - public TrTransform m_BaseWidgetXf_LS; - } - - struct GrabWidgetHoldPoint - { - // ReSharper disable once NotAccessedField.Local - public InputManager.ControllerName m_Name; - public float m_BirthTime; - public Vector3 m_Pos; // where controller is holding the widget - public Quaternion m_Rot; - } - - class InputStateConfig - { - public bool m_AllowDrawing; - public bool m_AllowMovement; - public bool m_ShowGizmo; - } - - enum FadeState - { - None, - FadeOn, - FadeOff - } - - enum GrabWidgetState - { - None, - OneHand, - TwoHands - } - - enum GrabWorldState - { - Normal, - ResettingTransform, - ResetDone - } - - private enum WorldTransformResetState - { - Default, - Requested, - FadingToBlack, - FadingToScene, - } - - enum RotationType - { - All, - RollOnly - } - - enum GrabIntersectionState - { - RequestIntersections, - ReadBrush, - ReadWand - } - - // ------------------------------------------------------------ - // Inspector data (read-only even if public) - // ------------------------------------------------------------ - - public GameObject m_SketchSurface; - public SketchMemoryScript.PlaybackMode m_DefaultSketchPlaybackMode; - public float m_GazeMaxAngleFromPointing = 85.0f; - public float m_GazeMaxAngleFacingToForward = 80.0f; - - [SerializeField] bool m_AtlasIconTextures; - - [SerializeField] SaveIconTool m_SaveIconTool; - [SerializeField] DropCamWidget m_DropCam; - [SerializeField] string m_CreditsSketchFilename; - [SerializeField] string m_AshleysSketchFilename; - [SerializeField] float m_DefaultSketchLoadSpeed; - [SerializeField] GameObject m_TransformGizmoPrefab; - - [SerializeField] GameObject m_RotationIconPrefab; - [SerializeField] float m_GazeMaxAngleFromFacing = 70.0f; - [SerializeField] float m_GazeMaxDistance = 10.0f; - [SerializeField] float m_GazeControllerPointingDistance; - [SerializeField] float m_GazePanelDectivationDelay = 0.25f; - - [SerializeField] GameObject m_UIReticle; - [SerializeField] GameObject m_UIReticleMobile; - [SerializeField] GameObject m_UIReticleSixDofController; - - [SerializeField] float m_DoubleTapWindow; - [SerializeField] float m_PushPullScale; - [SerializeField] RotationCursorScript m_RotationCursor; - [SerializeField] float m_RotationMaxAngle; - - [SerializeField] float m_RotationScalar; - [SerializeField] float m_RotationRollScalar; - [SerializeField] float m_PanScalar; - - [SerializeField] float m_AdjustToolSizeScalar; - - [SerializeField] GameObject m_IRCChatPrefab; - [SerializeField] GameObject m_YouTubeChatPrefab; - [SerializeField] GameObject m_Decor; - [SerializeField] BaseTool.ToolType m_InitialTool = BaseTool.ToolType.SketchSurface; - [SerializeField] string m_ReleaseNotesURL; - [SerializeField] string m_HelpCenterURL; - [SerializeField] string m_ThirdPartyNoticesURL; - [SerializeField] string m_TosURL; - [SerializeField] string m_PrivacyURL; - [SerializeField] string m_QuestSideLoadingHowToURL; - - [Multiline] - [SerializeField] string m_ContributionPromoText; - [SerializeField] string m_ContributionURL; - - [SerializeField] float m_WorldTransformMinScale = .1f; - [SerializeField] float m_WorldTransformMaxScale = 10.0f; - - [Header("Undo/Redo Hold")] - [SerializeField] float m_UndoRedoHold_DurationBeforeStart; - [SerializeField] float m_UndoRedoHold_RepeatInterval; - - [Header("Pin Cushion")] - [SerializeField] GameObject m_PinCushionPrefab; - - [Header("Grabbing and tossing")] - [SerializeField] float m_GrabWorldFadeSpeed = 8.0f; - [SerializeField] Color m_GrabWorldGridColor = new Color(0.0f, 1.0f, 1.0f, 0.2f); - [SerializeField] ControllerGrabVisuals m_ControllerGrabVisuals; - [SerializeField] float m_WidgetGpuIntersectionRadius; - - [Header("Saving")] - [SerializeField] int m_NumStrokesForSaveIcon = 50; - - [NonSerialized] public Color m_GrabHighlightActiveColor; - [NonSerialized] public bool m_DisableWorldGrabbing = false; - - /// Throwing an object faster than this means it's a "toss". Units are m/s. - public float m_TossThresholdMeters = 3f; - /// Angular motion contributes more towards the toss velocity the larger the object is; - /// or rather, the larger the distance between the grab point and the object's center. - /// To prevent large objects from being too-easily-tossed, bound that distance. - public float m_TossMaxPivotDistMeters = 0.33f; - - // ------------------------------------------------------------ - // Internal data - // ------------------------------------------------------------ - - private SketchSurfacePanel m_SketchSurfacePanel; - private SketchMemoryScript.PlaybackMode m_SketchPlaybackMode; - private GameObject m_TransformGizmo; - private TransformGizmoScript m_TransformGizmoScript; - private GameObject m_RotationIcon; - private float m_MouseDeltaX; - private float m_MouseDeltaY; - private float m_MouseDeltaXScaled; - private float m_MouseDeltaYScaled; - private float m_PositionOffsetResetTapTime; - private bool m_EatToolScaleInput; - - private PanelManager m_PanelManager; - private WidgetManager m_WidgetManager; - private PinCushion m_PinCushion; - private bool m_EatPinCushionInput; - - // This is the gaze that was used to compute m_CurrentGazeHitPoint. - // It is not a general substitute for ViewpointScript.Gaze. - private Ray m_CurrentGazeRay; - private Quaternion m_CurrentHeadOrientation; - private GazeResult[] m_GazeResults; - private int m_CurrentGazeObject; - private bool m_EatInputGazeObject; - private Vector3 m_CurrentGazeHitPoint; - private Ray m_GazeControllerRay; - private Ray m_GazeControllerRayActivePanel; - private bool m_ForcePanelActivation = false; - private float m_GazePanelDectivationCountdown; - private bool m_PanelsVisibilityRequested; - - // Previously Experimental-Model only - private bool m_HeadOffset; - - float m_UndoHold_Timer; - float m_RedoHold_Timer; - - // Grab world member variables. - struct GrabState - { - public InputManager.ControllerName name; - public TrTransform grabTransform; - public bool grabbingWorld; - public bool grabbingGroup; - public bool startedGrabInsideWidget; - public bool eatInput; - private GrabWidget lastWidgetIntersect; - - public void SetHadBestGrabAndTriggerHaptics(GrabWidgetData data) - { - bool dormant = WidgetManager.m_Instance.WidgetsDormant; - if (data != null && !data.m_WidgetScript.AllowDormancy) - { - dormant = false; - } - GrabWidget newInsideWidget = (data != null && !dormant) ? data.m_WidgetScript : null; - if (sm_enableGrabHaptics && newInsideWidget != lastWidgetIntersect) - { - // state changed - if (newInsideWidget != null) - { - // transitioning in - InputManager.m_Instance.TriggerHaptics(name, data.m_WidgetScript.HapticDuration); - } - else - { - // transitioning out - InputManager.m_Instance.TriggerHaptics(name, 0.03f); - } - } - lastWidgetIntersect = newInsideWidget; - } - - public void ClearInsideWidget() - { - lastWidgetIntersect = null; - } - } - private GrabState m_GrabBrush = new GrabState { name = InputManager.ControllerName.Brush }; - private GrabState m_GrabWand = new GrabState { name = InputManager.ControllerName.Wand }; - - private WorldTransformResetState m_WorldTransformResetState = WorldTransformResetState.Default; - private TrTransform m_WorldTransformResetXf = TrTransform.identity; // set when reset requested - private GrabWorldState m_GrabWorldState = GrabWorldState.Normal; - private float m_WorldTransformFadeAmount; - private bool m_AllowWorldTransformLastFrame = false; - private bool m_WorldBeingGrabbed; - private TrTransform m_xfDropCamReset_RS; - - struct GpuIntersectionResult - { - public GpuIntersector.FutureModelResult result; - public List resultList; - } - private Queue m_BrushResults; - private Queue m_WandResults; - private int m_WidgetGpuIntersectionLayer; - - private GrabWidget m_CurrentGrabWidget; - private GrabWidget m_MaybeDriftingGrabWidget; // use only to clear drift - - // References to widgets, cached in the UpdateGrab_None, to be used by helper functions - // for the remainder of the frame. - private GrabWidget m_PotentialGrabWidgetBrush; - private GrabWidget m_PotentialGrabWidgetWand; - - // Flags for the explaining if the m_PotentialGrabWidget_x widgets are able to be interacted with. - // Cached in the UpdateGrab_None, used for the remainder of the frame. - private bool m_PotentialGrabWidgetBrushValid; - private bool m_PotentialGrabWidgetWandValid; - - // References to widget metadata, cached in UpdateGrab_None, to be re-used on "off frames" - // when the GPU intersector is not refreshing the nearest widget to the respective controller. - private GrabWidgetData m_BackupBrushGrabData; - private GrabWidgetData m_BackupWandGrabData; - - private GrabWidgetState m_GrabWidgetState; - private GrabWidgetControllerInfo m_GrabWidgetOneHandInfo; - private TrTransform m_GrabWidgetTwoHandBrushPrev; - private TrTransform m_GrabWidgetTwoHandWandPrev; - private Queue m_GrabWidgetHoldHistory; - - private Quaternion m_RotationOrigin; - private Vector2 m_RotationCursorOffset; - - private bool m_RotationRollActive; - private float m_RotationResetTapTime; - - private RotationType m_CurrentRotationType; - private bool m_AutoOrientAfterRotation; - - private Vector3 m_SurfaceForward; - private Vector3 m_SurfaceRight; - private Vector3 m_SurfaceUp; - - private Vector3 m_SurfaceLockOffset; - private Vector3 m_SurfaceLockBaseSurfacePosition; - private Vector3 m_SurfaceLockBaseControllerPosition; - private Quaternion m_SurfaceLockBaseHeadRotation; - private Quaternion m_SurfaceLockBaseControllerRotation; - private Quaternion m_SurfaceLockBaseSurfaceRotation; - private InputManager.ControllerName m_SurfaceLockActingController; - private float m_SurfaceLockControllerBaseScalar; - private float m_SurfaceLockControllerScalar; - - private bool m_PositioningPanelWithHead; - private Quaternion m_PositioningPanelBaseHeadRotation; - private Vector3 m_PositioningPanelOffset; - private float m_PositioningTimer; - private float m_PositioningSpeed; - - private DraftingVisibilityOption m_DraftingVisibility = DraftingVisibilityOption.Visible; - - private Vector3 m_SketchOrigin; - - private ControlsType m_ControlsType; - private GrabWidget m_IRCChatWidget; - private GrabWidget m_YouTubeChatWidget; - private MultiCamCaptureRig m_MultiCamCaptureRig; - private CameraPathCaptureRig m_CameraPathCaptureRig; - - private bool m_ViewOnly = false; - - private InputState m_CurrentInputState; - private InputStateConfig[] m_InputStateConfigs; - - private GrabIntersectionState m_CurrentGrabIntersectionState; - - private float m_WorldTransformSpeedSmoothed; - - // ------------------------------------------------------------ - // Properties and events - // ------------------------------------------------------------ - - public MultiCamCaptureRig MultiCamCaptureRig - { - get { return m_MultiCamCaptureRig; } - } - - public CameraPathCaptureRig CameraPathCaptureRig - { - get { return m_CameraPathCaptureRig; } - } - - public ControllerGrabVisuals ControllerGrabVisuals - { - get { return m_ControllerGrabVisuals; } - } - - public SketchMemoryScript.PlaybackMode SketchPlaybackMode - { - get { return m_SketchPlaybackMode; } - set { m_SketchPlaybackMode = value; } - } - - public Transform m_Canvas - { - get { return App.Instance.m_CanvasTransform; } - } - - public ControlsType ActiveControlsType - { - get { return m_ControlsType; } - set { m_ControlsType = value; } - } - - public float WorldTransformMinScale - { - get - { - return App.UserConfig.Flags.UnlockScale ? m_WorldTransformMinScale * 0.01f : - m_WorldTransformMinScale; - } - } - - public float WorldTransformMaxScale - { - get - { - return App.UserConfig.Flags.UnlockScale ? m_WorldTransformMaxScale * 10.0f : - m_WorldTransformMaxScale; - } - } - - public void SetInitialTool(BaseTool.ToolType rType) - { - m_InitialTool = rType; - } - - public void SetInFreePaintMode(bool bFreePaint) - { - m_SketchSurfacePanel.SetInFreePaintMode(bFreePaint); - } - - public float GazeMaxDistance - { - get { return m_GazeMaxDistance; } - } - - public InputManager.ControllerName OneHandGrabController - { - get - { - return m_CurrentGrabWidget != null ? - m_GrabWidgetOneHandInfo.m_Name : - InputManager.ControllerName.None; - } - } - - public InputManager.ControllerName PotentialOneHandGrabController(GrabWidget widget) - { - if (m_PotentialGrabWidgetBrush == widget) - { - return InputManager.ControllerName.Brush; - } - else if (m_PotentialGrabWidgetWand == widget) - { - return InputManager.ControllerName.Wand; - } - return OneHandGrabController; - } - - public Vector3 GetSurfaceForward() { return m_SurfaceForward; } - public Vector3 GetSurfaceUp() { return m_SurfaceUp; } - public Vector3 GetSurfaceRight() { return m_SurfaceRight; } - public Vector3 GetSketchOrigin() { return m_SketchOrigin; } - public float GetDefaultSketchLoadSpeed() { return m_DefaultSketchLoadSpeed; } - public Quaternion GetCurrentHeadOrientation() { return m_CurrentHeadOrientation; } - public Vector3 GetUIReticlePos() { return m_UIReticle.transform.position; } - public Vector3 GetSweetSpotPos() { return m_PanelManager.m_SweetSpot.transform.position; } - public void SetSketchOrigin(Vector3 vOrigin) { m_SketchOrigin = vOrigin; } - - public void EatGazeObjectInput() - { - m_EatInputGazeObject = true; - m_GazePanelDectivationCountdown = 0.0f; - PointerManager.m_Instance.EatLineEnabledInput(); - SketchSurfacePanel.m_Instance.EatToolsInput(); - } - public void EatToolScaleInput() { m_EatToolScaleInput = true; } - public void EatGrabInput() - { - m_GrabWand.eatInput = true; - m_GrabBrush.eatInput = true; - } - - public bool ShouldRespondToPadInput(InputManager.ControllerName name) - { - if (name == InputManager.ControllerName.Brush && m_CurrentGazeObject != -1) - { - return m_PanelManager.GetPanel(m_CurrentGazeObject).BrushPadAnimatesOnHover(); - } - return !m_EatToolScaleInput && SketchSurfacePanel.m_Instance.CanAdjustToolSize(); - } - public void ForcePanelActivation(bool bForce) - { - m_ForcePanelActivation = bForce; - if (m_ForcePanelActivation) - { - m_GazePanelDectivationCountdown = m_GazePanelDectivationDelay; - } - } - public bool IsUserInteractingWithUI() - { - return (m_CurrentGazeObject != -1) || (m_GazePanelDectivationCountdown > 0.0f); - } - public bool IsUIBlockingUndoRedo() - { - if (m_CurrentGazeObject != -1) - { - return m_PanelManager.GetPanel(m_CurrentGazeObject).UndoRedoBlocked(); - } - return false; - } - public bool IsUserAbleToInteractWithAnyWidget() - { - return IsUserInteractingWithAnyWidget() || - (m_PotentialGrabWidgetBrush != null && m_PotentialGrabWidgetBrushValid) || - (m_PotentialGrabWidgetWand != null && m_PotentialGrabWidgetWandValid); - } - public bool IsUserInteractingWithAnyWidget() { return m_CurrentGrabWidget != null; } - public bool IsUserGrabbingAnyPanel() - { - return (m_CurrentGrabWidget != null && m_CurrentGrabWidget is PanelWidget); - } - public bool IsUsersBrushIntersectingWithSelectionWidget() - { - return (m_PotentialGrabWidgetBrush != null && - m_PotentialGrabWidgetBrushValid && - m_PotentialGrabWidgetBrush is SelectionWidget); - } - public bool IsUserIntersectingWithSelectionWidget() - { - return IsUsersBrushIntersectingWithSelectionWidget() || - (m_PotentialGrabWidgetWand != null && - m_PotentialGrabWidgetWandValid && - m_PotentialGrabWidgetWand is SelectionWidget); - } - public bool IsUserInteractingWithSelectionWidget() - { - return (m_CurrentGrabWidget != null && m_CurrentGrabWidget is SelectionWidget); - } - - public bool IsUserGrabbingWorld() { return m_GrabWand.grabbingWorld || m_GrabBrush.grabbingWorld; } - public bool IsUserGrabbingWorldWithBrushHand() { return m_GrabBrush.grabbingWorld; } - public bool IsUserTransformingWorld() { return m_GrabWand.grabbingWorld && m_GrabBrush.grabbingWorld; } - public float GetGazePanelActivationRatio() { return m_GazePanelDectivationCountdown / m_GazePanelDectivationDelay; } - public bool IsCurrentGrabWidgetPinned() { return IsUserInteractingWithAnyWidget() && m_CurrentGrabWidget.Pinned; } - public bool CanCurrentGrabWidgetBePinned() { return IsUserInteractingWithAnyWidget() && m_CurrentGrabWidget.AllowPinning; } - public bool DidUserGrabWithBothInside() { return m_GrabBrush.startedGrabInsideWidget && m_GrabWand.startedGrabInsideWidget; } - public bool IsUserGrabbingWidget(GrabWidget widget) { return widget == m_CurrentGrabWidget; } - public bool IsUserTwoHandGrabbingWidget() { return m_GrabWidgetState == GrabWidgetState.TwoHands; } - public bool IsPinCushionShowing() { return m_PinCushion.IsShowing(); } - public bool IsUserLookingAtPanel(BasePanel panel) - { - return m_CurrentGazeObject > -1 && - m_PanelManager.GetAllPanels()[m_CurrentGazeObject].m_Panel == panel; - } - - public SaveIconTool GetSaveIconTool() - { - return m_SaveIconTool; - } - - public DropCamWidget GetDropCampWidget() - { - return m_DropCam; - } - - public bool IsGrabWorldStateStable() - { - return m_GrabWorldState == GrabWorldState.Normal; - } - - // Internal: modify Coords.ScenePose or Coords.CanvasPose depending on the - // state of m_InTransformCanvasMode - TrTransform GrabbedPose - { - get - { - return App.Scene.Pose; - } - set - { - App.Scene.Pose = value; - } - } - - public Transform GazeObjectTransform() - { - if (m_CurrentGazeObject != -1) - { - return m_PanelManager.GetPanel(m_CurrentGazeObject).transform; - } - return null; - } - - public void ForceShowUIReticle(bool bVisible) - { - m_UIReticle.SetActive(bVisible); - } - - public void SetUIReticleTransform(Vector3 vPos, Vector3 vForward) - { - m_UIReticle.transform.position = vPos; - m_UIReticle.transform.forward = vForward; - } - - public bool AtlasIconTextures - { - get { return m_AtlasIconTextures; } - } - - public IconTextureAtlas IconTextureAtlas - { - get { return GetComponent(); } - } - public GrabWidget CurrentGrabWidget => m_CurrentGrabWidget; - - void DismissPopupOnCurrentGazeObject(bool force) - { - if (m_CurrentGazeObject != -1) - { - m_PanelManager.GetPanel(m_CurrentGazeObject).CloseActivePopUp(force); - } - } - - void Awake() - { - m_Instance = this; - - BrushController.m_Instance.BrushSetToDefault += OnBrushSetToDefault; - - IconTextureAtlas.Init(); - - m_MultiCamCaptureRig = GetComponentInChildren(true); - m_MultiCamCaptureRig.Init(); - - m_CameraPathCaptureRig = GetComponentInChildren(true); - m_CameraPathCaptureRig.Init(); - - m_SketchSurfacePanel = m_SketchSurface.GetComponent(); - m_PanelManager = GetComponent(); - m_PanelManager.Init(); - InitGazePanels(); - - m_WidgetManager = GetComponent(); - m_WidgetManager.Init(); - - m_InputStateConfigs = new InputStateConfig[(int)InputState.Num]; - for (int i = 0; i < (int)InputState.Num; ++i) - { - m_InputStateConfigs[i] = new InputStateConfig(); - m_InputStateConfigs[i].m_AllowDrawing = false; - m_InputStateConfigs[i].m_AllowMovement = true; - m_InputStateConfigs[i].m_ShowGizmo = false; - } - - m_InputStateConfigs[(int)InputState.Standard].m_AllowDrawing = true; - m_InputStateConfigs[(int)InputState.Pan].m_AllowDrawing = true; - m_InputStateConfigs[(int)InputState.HeadLock].m_AllowDrawing = true; - m_InputStateConfigs[(int)InputState.ControllerLock].m_AllowDrawing = true; - m_InputStateConfigs[(int)InputState.PushPull].m_AllowDrawing = true; - - m_InputStateConfigs[(int)InputState.Pan].m_AllowMovement = false; - m_InputStateConfigs[(int)InputState.Rotation].m_AllowMovement = false; - m_InputStateConfigs[(int)InputState.ControllerLock].m_AllowMovement = false; - m_InputStateConfigs[(int)InputState.PushPull].m_AllowMovement = false; - m_InputStateConfigs[(int)InputState.BrushSize].m_AllowMovement = false; - - m_InputStateConfigs[(int)InputState.Pan].m_ShowGizmo = true; - m_InputStateConfigs[(int)InputState.Rotation].m_ShowGizmo = true; - m_InputStateConfigs[(int)InputState.HeadLock].m_ShowGizmo = true; - m_InputStateConfigs[(int)InputState.PushPull].m_ShowGizmo = true; - - m_CurrentGazeRay = new Ray(Vector3.zero, Vector3.forward); - m_GazeControllerRay = new Ray(Vector3.zero, Vector3.forward); - m_GazeControllerRayActivePanel = new Ray(Vector3.zero, Vector3.forward); - - m_GrabWidgetHoldHistory = new Queue(); - m_GrabWidgetOneHandInfo = new GrabWidgetControllerInfo(); - - // Initialize world grip members. - m_GrabBrush.grabTransform = TrTransform.identity; - m_GrabWand.grabTransform = TrTransform.identity; - - m_BrushResults = new Queue(); - m_WandResults = new Queue(); - m_WidgetGpuIntersectionLayer = LayerMask.NameToLayer("GpuIntersection"); - m_CurrentGrabIntersectionState = GrabIntersectionState.RequestIntersections; - } - - public void InitGazePanels() - { - // Find all gaze panels. - int iNumGazePanels = m_PanelManager.GetAllPanels().Count; - m_GazeResults = new GazeResult[iNumGazePanels]; - for (int i = 0; i < iNumGazePanels; ++i) - { - m_GazeResults[i] = new GazeResult(); - m_GazeResults[i].m_HitWithGaze = false; - m_GazeResults[i].m_HitWithController = false; - m_GazeResults[i].m_WithinView = false; - m_GazeResults[i].m_GazePosition = new Vector3(); - } - } - - public void OnEnable() - { - // This needs to run before other tools initialize, which is why it's running in OnEnable. - // The sequence is Awake(), OnEnable(), Start(). - if (App.VrSdk.GetControllerDof() == VrSdk.DoF.Six) - { - SetInFreePaintMode(true); - SetInitialTool(BaseTool.ToolType.FreePaintTool); - } - } - - void Start() - { - m_TransformGizmo = (GameObject)Instantiate(m_TransformGizmoPrefab); - m_TransformGizmo.transform.parent = transform; - m_TransformGizmoScript = m_TransformGizmo.GetComponent(); - m_TransformGizmo.SetActive(false); - - m_RotationIcon = (GameObject)Instantiate(m_RotationIconPrefab); - m_RotationIcon.transform.position = m_SketchSurface.transform.position; - m_RotationIcon.transform.parent = m_SketchSurface.transform; - m_RotationIcon.SetActive(false); - - GameObject pinCushionObj = (GameObject)Instantiate(m_PinCushionPrefab); - m_PinCushion = pinCushionObj.GetComponent(); - - m_PositionOffsetResetTapTime = 0.0f; - - m_UndoHold_Timer = m_UndoRedoHold_DurationBeforeStart; - m_RedoHold_Timer = m_UndoRedoHold_DurationBeforeStart; - - m_AutoOrientAfterRotation = true; - m_RotationCursor.gameObject.SetActive(false); - - ResetGrabbedPose(); - m_SketchOrigin = m_SketchSurface.transform.position; - - m_PanelManager.InitPanels(m_ControlsType == ControlsType.SixDofControllers); - - m_UIReticleMobile.SetActive(m_ControlsType == ControlsType.ViewingOnly); - m_UIReticleSixDofController.SetActive(m_ControlsType != ControlsType.ViewingOnly); - - m_PositioningPanelWithHead = false; - m_PositioningSpeed = 16.0f; - - m_CurrentRotationType = RotationType.All; - m_RotationResetTapTime = 0.0f; - - m_CurrentInputState = InputState.Standard; - - m_SketchSurfacePanel.EnableSpecificTool(m_InitialTool); - m_SurfaceLockControllerBaseScalar = m_SketchSurfacePanel.m_PanelSensitivity; - - //after initializing, start with gaze objects hidden - m_CurrentGazeObject = -1; - m_EatInputGazeObject = false; - - // Previously set to 0 in experimental builds - int hidePanelsDelay = 1; - - StartCoroutine(DelayedHidePanels(hidePanelsDelay)); - - m_DropCam.Show(false); - - m_GrabWidgetState = GrabWidgetState.None; - - UpdateDraftingVisibility(); - - m_DisableWorldGrabbing = false; - } - - private IEnumerator DelayedHidePanels(int frames) - { - int stall = frames; - while (stall-- > 0) - { - yield return null; - } - - m_PanelManager.HidePanelsForStartup(); - RequestPanelsVisibility(false); - } - - void Update() - { - // TODO: we need to figure out what transform to pass in here! - // Maybe best _just for now_ to use the scene transform? - TrTransform scenePose = App.Scene.Pose; - Shader.SetGlobalMatrix("xf_CS", scenePose.ToMatrix4x4()); - Shader.SetGlobalMatrix("xf_I_CS", scenePose.inverse.ToMatrix4x4()); - } - - void LateUpdate() - { - // Gracefully exits if we're not recording a video. - VideoRecorderUtils.SerializerNewUsdFrame(); - } - - public bool IsFreepaintToolReady() - { - return - !m_PinCushion.IsShowing() && - !PointerManager.m_Instance.IsStraightEdgeProxyActive() && - !InputManager.m_Instance.ControllersAreSwapping() && - (m_SketchSurfacePanel.IsSketchSurfaceToolActive() || - (m_SketchSurfacePanel.GetCurrentToolType() == BaseTool.ToolType.FreePaintTool)) - ; - } - - public void UpdateControls() - { - UnityEngine.Profiling.Profiler.BeginSample("SketchControlsScript.UpdateControls"); - m_SketchSurfacePanel.m_UpdatedToolThisFrame = false; - - // Verify controllers are available and prune state if they're not. - if ((App.VrSdk.GetControllerDof() == VrSdk.DoF.Six && - App.VrSdk.IsInitializingUnityXR) && App.VrSdk.IsHmdInitialized()) - { - m_PanelManager.SetVisible(false); - PointerManager.m_Instance.RequestPointerRendering(false); - return; - } - - //mouse movement - Vector2 mv = InputManager.m_Instance.GetMouseMoveDelta(); - m_MouseDeltaX = mv.x; - m_MouseDeltaY = mv.y; - - UpdateGazeObjectsAnimationState(); - UpdateCurrentGazeRay(); - m_SketchSurfacePanel.SetBacksideActive(m_CurrentGazeRay.origin); - m_PanelManager.UpdatePanels(); - - m_MouseDeltaXScaled = m_MouseDeltaX * GetAppropriateMovementScalar(); - m_MouseDeltaYScaled = m_MouseDeltaY * GetAppropriateMovementScalar(); - - //this is used for one-shot inputs that don't require state and do not change state - UpdateBaseInput(); - - UpdatePinCushionVisibility(); - - //if the pointer manager is processing, we don't want to respond to input - if (!PointerManager.m_Instance.IsMainPointerProcessingLine()) - { - - //see if we're grabbing a widget - UpdateGrab(); - - //see if we're looking at a gaze object - RefreshCurrentGazeObject(); - - // Tools allowed when widgets aren't grabbed. - bool bWidgetGrabOK = m_GrabWidgetState == GrabWidgetState.None; - - // If we don't have a widget held and we're not grabbing the world with the brush controller, - // update tools. - if (bWidgetGrabOK && !m_GrabBrush.grabbingWorld) - { - if (m_CurrentGazeObject != -1 && !m_WorldBeingGrabbed) - { - UpdateActiveGazeObject(); - - // Allow for standard input (like Undo / Redo) even when gazing at a panel. - if (m_CurrentInputState == InputState.Standard) - { - UpdateStandardInput(); - } - } - else - { - //standard input, no gaze object - if (m_InputStateConfigs[(int)m_CurrentInputState].m_AllowMovement) - { - m_SketchSurfacePanel.UpdateReticleOffset(m_MouseDeltaX, m_MouseDeltaY); - } - - switch (m_CurrentInputState) - { - case InputState.Standard: - UpdateStandardInput(); - break; - case InputState.Pan: - UpdatePanInput(); - break; - case InputState.Rotation: - UpdateRotationInput(); - break; - case InputState.HeadLock: - UpdateHeadLockInput(); - break; - case InputState.ControllerLock: - UpdateControllerLock(); - break; - case InputState.PushPull: - UpdatePushPullInput(); - break; - case InputState.Save: - UpdateSaveInput(); - break; - case InputState.Load: - UpdateLoadInput(); - break; - } - - //keep pointer locked in the right spot, even if it's hidden - if (m_SketchSurfacePanel.ActiveTool.LockPointerToSketchSurface()) - { - Vector3 vPointerPos = Vector3.zero; - Vector3 vPointerForward = Vector3.zero; - m_SketchSurfacePanel.GetReticleTransform(out vPointerPos, out vPointerForward, - (m_ControlsType == ControlsType.ViewingOnly)); - PointerManager.m_Instance.SetMainPointerPosition(vPointerPos); - PointerManager.m_Instance.SetMainPointerForward(vPointerForward); - } - - m_SketchSurfacePanel.AllowDrawing(m_InputStateConfigs[(int)m_CurrentInputState].m_AllowDrawing); - m_SketchSurfacePanel.UpdateCurrentTool(); - - PointerManager.m_Instance.AllowPointerPreviewLine(IsFreepaintToolReady()); - //keep transform gizmo at sketch surface pos - m_TransformGizmo.transform.position = m_SketchSurface.transform.position; - bool bGizmoActive = m_InputStateConfigs[(int)m_CurrentInputState].m_ShowGizmo && m_SketchSurfacePanel.ShouldShowTransformGizmo(); - m_TransformGizmo.SetActive(bGizmoActive); - } - } - } - - // Update any transition to a scene transform reset. - UpdateWorldTransformReset(); - - //update our line after all input and tools have chimed in on the state of it - PointerManager.m_Instance.UpdateLine(); - UnityEngine.Profiling.Profiler.EndSample(); - } - - public void UpdateControlsPostIntro() - { - m_PanelManager.UpdatePanels(); - UpdateCurrentGazeRay(); - UpdateGazeObjectsAnimationState(); - RefreshCurrentGazeObject(); - UpdateSwapControllers(); - if (m_CurrentGazeObject > -1) - { - UpdateActiveGazeObject(); - } - } - - public void UpdateControlsForLoading() - { - UpdateCurrentGazeRay(); - m_PanelManager.UpdatePanels(); - UpdateGazeObjectsAnimationState(); - UpdateGrab(); - UpdateWorldTransformReset(); - - if (m_GrabWidgetState == GrabWidgetState.None && m_CurrentGazeObject == -1 && - m_SketchSurfacePanel.ActiveTool.AvailableDuringLoading() && - !m_GrabBrush.grabbingWorld) - { - m_SketchSurfacePanel.UpdateCurrentTool(); - } - } - - public void UpdateControlsForReset() - { - UpdateGrab(); - UpdateCurrentGazeRay(); - UpdatePinCushionVisibility(); - m_PanelManager.UpdatePanels(); - UpdateGazeObjectsAnimationState(); - PointerManager.m_Instance.UpdateLine(); - } - - public void UpdateControlsForUploading() - { - UpdateCurrentGazeRay(); - UpdatePinCushionVisibility(); - m_PanelManager.UpdatePanels(); - UpdateGazeObjectsAnimationState(); - } - - public void UpdateControlsForMemoryExceeded() - { - UpdateGrab(); - m_SketchSurfacePanel.m_UpdatedToolThisFrame = false; - m_PanelManager.UpdatePanels(); - UpdateCurrentGazeRay(); - UpdateGazeObjectsAnimationState(); - RefreshCurrentGazeObject(); - if (m_CurrentGazeObject > -1) - { - UpdateActiveGazeObject(); - } - } - - void UpdatePinCushionVisibility() - { - // If the pin cushion is showing and the user cancels, eat the input. - // if (m_PinCushion.IsShowing()) - // { - // if (InputManager.m_Instance.GetCommand(InputManager.SketchCommands.Activate) || - // InputManager.Brush.GetControllerGrip() || - // InputManager.Wand.GetControllerGrip() || - // IsUserInteractingWithAnyWidget() || - // IsUserInteractingWithUI()) - // { - // m_EatPinCushionInput = true; - // } - // } - - // If our tool wants the input blocked, maintain the input eat state until - // after the user has let off input. - if (m_SketchSurfacePanel.ActiveTool.BlockPinCushion() || !CanUsePinCushion()) - { - m_EatPinCushionInput = true; - } - - bool show = - InputManager.m_Instance.GetCommand(InputManager.SketchCommands.ShowPinCushion); - m_PinCushion.ShowPinCushion(show && !m_EatPinCushionInput); - m_EatPinCushionInput = m_EatPinCushionInput && show; - } - - bool CanUsePinCushion() - { - return (m_ControlsType == ControlsType.SixDofControllers) && - m_PanelManager.AdvancedModeActive() && - !InputManager.m_Instance.GetCommand(InputManager.SketchCommands.Activate) && - !InputManager.Brush.GetControllerGrip() && - !InputManager.Wand.GetControllerGrip() && - !IsUserInteractingWithAnyWidget() && - !IsUserInteractingWithUI() && - !m_SketchSurfacePanel.ActiveTool.BlockPinCushion() && - App.Instance.IsInStateThatAllowsPainting(); - } - - void UpdateCurrentGazeRay() - { - var head = ViewpointScript.Head; - m_CurrentGazeRay = new Ray(head.position, head.forward); - m_CurrentHeadOrientation = head.rotation; - - // We use the gaze ray for certain shader effects - like edge falloff. - Shader.SetGlobalVector("_WorldSpaceRootCameraPosition", m_CurrentGazeRay.origin); - bool hasController = m_ControlsType == ControlsType.SixDofControllers; - if (hasController) - { - if (InputManager.Brush.IsTrackedObjectValid) - { - Transform rAttachPoint = InputManager.m_Instance.GetBrushControllerAttachPoint(); - m_GazeControllerRay.direction = rAttachPoint.forward; - m_GazeControllerRay.origin = rAttachPoint.position; - } - else - { - // If the brush controller isn't tracked, put our controller ray out of the way. - float fBig = 9999999.0f; - m_GazeControllerRay.direction = Vector3.one; - m_GazeControllerRay.origin = new Vector3(fBig, fBig, fBig); - } - - m_GazeControllerRayActivePanel.direction = m_GazeControllerRay.direction; - m_GazeControllerRayActivePanel.origin = m_GazeControllerRay.origin; - m_GazeControllerRayActivePanel.origin -= (m_GazeControllerRayActivePanel.direction * 0.5f); - } - } - - public void UpdateGazeObjectsAnimationState() - { - // Are the panels allowed to be visible? - bool isSixDof = m_ControlsType == ControlsType.SixDofControllers; - if ((!isSixDof) || - (InputManager.Wand.IsTrackedObjectValid && - !m_SketchSurfacePanel.ActiveTool.HidePanels() && - !App.Instance.IsLoading())) - { - // Transition panels according to requested visibility. - m_PanelManager.SetVisible(m_PanelsVisibilityRequested); - } - else - { - // Transition out. - m_PanelManager.SetVisible(false); - } - } - - void UpdateBaseInput() - { - UnityEngine.Profiling.Profiler.BeginSample("SketchControlScript.UpdateBaseInput"); - if (m_ControlsType == ControlsType.SixDofControllers) - { - m_PanelManager.UpdateWandOrientationControls(); - } - - //allow tool scaling if we're not drawing and our input device is active - bool bScaleInputActive = InputManager.m_Instance.GetCommand(InputManager.SketchCommands.Scale); - bool bScaleCommandActive = - bScaleInputActive - && !InputManager.m_Instance.GetCommand(InputManager.SketchCommands.Activate) - && m_GrabBrush.grabbingWorld == false - && m_CurrentGazeObject == -1 // free up swipe for use by gaze object - && (m_ControlsType != ControlsType.SixDofControllers || InputManager.Brush.IsTrackedObjectValid) - // TODO:Mikesky - very hacky - && SketchSurfacePanel.m_Instance.ActiveTool.m_Type != BaseTool.ToolType.MultiCamTool; - - if (m_EatToolScaleInput) - { - m_EatToolScaleInput = bScaleInputActive; - } - - if (bScaleCommandActive && !m_EatToolScaleInput) - { - if (m_GrabWidgetState == GrabWidgetState.None) - { - //send scale command down to current tool - m_SketchSurfacePanel.UpdateToolSize( - m_AdjustToolSizeScalar * InputManager.m_Instance.GetAdjustedBrushScrollAmount()); - } - - //ugly, but brush size is becoming not an input state - m_MouseDeltaX = 0.0f; - m_MouseDeltaY = 0.0f; - } - - UpdateSwapControllers(); - UnityEngine.Profiling.Profiler.EndSample(); - } - - void UpdateSwapControllers() - { - // Don't allow controller swap in first run intro. - // Don't allow controller swap if we're grabbing a widget. - // Don't allow controller swap if a Logitech pen is present. - if (!TutorialManager.m_Instance.TutorialActive() && - m_GrabWidgetState == GrabWidgetState.None && - !App.VrSdk.VrControls.LogitechPenIsPresent()) - { - if (InputManager.m_Instance.GetCommandDown(InputManager.SketchCommands.SwapControls)) - { - DoSwapControls(); - } - } - } - - public static void DoSwapControls() - { - InputManager.m_Instance.WandOnRight = !InputManager.m_Instance.WandOnRight; - InputManager.m_Instance.GetControllerBehavior(InputManager.ControllerName.Brush) - .DisplayControllerSwapAnimation(); - InputManager.m_Instance.GetControllerBehavior(InputManager.ControllerName.Wand) - .DisplayControllerSwapAnimation(); - AudioManager.m_Instance.PlayControllerSwapSound( - InputManager.m_Instance.GetControllerPosition(InputManager.ControllerName.Brush)); - } - - void UpdateStandardInput() - { - UnityEngine.Profiling.Profiler.BeginSample("SketchControlScript.UpdateStandardInput"); - //debug keys - if (App.UserConfig.Flags.AdvancedKeyboardShortcuts) - { - var camTool = SketchSurfacePanel.m_Instance.ActiveTool as MultiCamTool; - - if (InputManager.m_Instance.GetKeyboardShortcutDown(InputManager.KeyboardShortcut.SaveNew)) - { - IssueGlobalCommand(GlobalCommands.SaveNew, 1); - } - else if (InputManager.m_Instance.GetKeyboardShortcutDown( - InputManager.KeyboardShortcut.SwitchCamera) && camTool != null) - { - camTool.ExternalObjectNextCameraStyle(); // For monoscopic mode - } - else if (InputManager.m_Instance.GetKeyboardShortcutDown( - InputManager.KeyboardShortcut.ViewOnly)) - { - IssueGlobalCommand(GlobalCommands.ViewOnly); - } - else if (InputManager.m_Instance.GetKeyboardShortcutDown( - InputManager.KeyboardShortcut.ToggleScreenMirroring)) - { - ViewpointScript.m_Instance.ToggleScreenMirroring(); - } - else if (InputManager.m_Instance.GetKeyboardShortcutDown( - InputManager.KeyboardShortcut.PreviousTool)) - { - m_SketchSurfacePanel.PreviousTool(); - } - else if (InputManager.m_Instance.GetKeyboardShortcutDown( - InputManager.KeyboardShortcut.NextTool)) - { - m_SketchSurfacePanel.NextTool(); - } - else if (InputManager.m_Instance.GetKeyboardShortcutDown( - InputManager.KeyboardShortcut.CycleSymmetryMode)) - { - var cur = PointerManager.m_Instance.CurrentSymmetryMode; - var next = (cur == SymmetryMode.None) ? SymmetryMode.SinglePlane - : (cur == SymmetryMode.SinglePlane) ? SymmetryMode.DebugMultiple - : (cur == SymmetryMode.DebugMultiple) ? SymmetryMode.MultiMirror - : (cur == SymmetryMode.MultiMirror) ? SymmetryMode.TwoHanded - : SymmetryMode.None; - PointerManager.m_Instance.CurrentSymmetryMode = next; - } - else if (InputManager.m_Instance.GetKeyboardShortcutDown( - InputManager.KeyboardShortcut.Export)) - { - StartCoroutine(ExportCoroutine()); - } - else if (InputManager.m_Instance.GetKeyboardShortcutDown( - InputManager.KeyboardShortcut.StoreHeadTransform) && - InputManager.m_Instance.GetAnyShift()) - { - Transform head = ViewpointScript.Head; - PlayerPrefs.SetFloat("HeadOffset_localPositionX", head.localPosition.x); - PlayerPrefs.SetFloat("HeadOffset_localPositionY", head.localPosition.y); - PlayerPrefs.SetFloat("HeadOffset_localPositionZ", head.localPosition.z); - PlayerPrefs.SetFloat("HeadOffset_localRotationX", head.localRotation.x); - PlayerPrefs.SetFloat("HeadOffset_localRotationY", head.localRotation.y); - PlayerPrefs.SetFloat("HeadOffset_localRotationZ", head.localRotation.z); - PlayerPrefs.SetFloat("HeadOffset_localRotationW", head.localRotation.w); - } - else if (InputManager.m_Instance.GetKeyboardShortcutDown( - InputManager.KeyboardShortcut.RecallHeadTransform)) - { - Transform head = ViewpointScript.Head; - // Toggle the head offset. - if (m_HeadOffset) - { - // Remove the offset. - Transform originalParent = head.parent; - head.SetParent(head.parent.parent); - GameObject.DestroyImmediate(originalParent.gameObject); - m_HeadOffset = false; - } - else - { - // Add the offset. - GameObject newParent = new GameObject(); - newParent.transform.SetParent(head.parent); - newParent.transform.localPosition = Vector3.zero; - newParent.transform.localRotation = Quaternion.identity; - newParent.transform.localScale = Vector3.one; - head.SetParent(newParent.transform); - TrTransform offsetTransform = TrTransform.TR( - new Vector3( - PlayerPrefs.GetFloat("HeadOffset_localPositionX", 0), - PlayerPrefs.GetFloat("HeadOffset_localPositionY", 1.5f), - PlayerPrefs.GetFloat("HeadOffset_localPositionZ", 0)), - new Quaternion( - PlayerPrefs.GetFloat("HeadOffset_localRotationX", 0), - PlayerPrefs.GetFloat("HeadOffset_localRotationY", 0), - PlayerPrefs.GetFloat("HeadOffset_localRotationZ", 0), - PlayerPrefs.GetFloat("HeadOffset_localRotationW", 1))); - TrTransform originalTransformInverse = TrTransform.FromLocalTransform(head).inverse; - TrTransform newParentTransform = offsetTransform * originalTransformInverse; - newParent.transform.localPosition = newParentTransform.translation; - newParent.transform.localRotation = newParentTransform.rotation; - m_HeadOffset = true; - } - } - else if (InputManager.m_Instance.GetKeyboardShortcutDown( - InputManager.KeyboardShortcut.ToggleLightType)) - { - // Toggle between per-pixel & SH lighting on the secondary directional light - Light secondaryLight = App.Scene.GetLight((1)); - if (LightRenderMode.ForceVertex == secondaryLight.renderMode) - { - secondaryLight.renderMode = LightRenderMode.ForcePixel; - } - else - { - secondaryLight.renderMode = LightRenderMode.ForceVertex; - } - } - else if (InputManager.m_Instance.GetKeyboardShortcutDown( - InputManager.KeyboardShortcut.TossWidget)) - { - m_WidgetManager.TossNearestWidget(); - } - else if (InputManager.m_Instance.GetKeyboardShortcutDown( - InputManager.KeyboardShortcut.Reset)) - { - App.Instance.SetDesiredState(App.AppState.LoadingBrushesAndLighting); - } - else if (InputManager.m_Instance.GetKeyboardShortcutDown( - InputManager.KeyboardShortcut.FlyMode)) - { - SketchSurfacePanel.m_Instance.EnableSpecificTool(BaseTool.ToolType.FlyTool); - } - else if (App.Config.m_ToggleProfileOnAppButton && - (InputManager.Wand.GetVrInputDown(VrInput.Button03) || - InputManager.m_Instance.GetKeyboardShortcutDown( - InputManager.KeyboardShortcut.ToggleProfile))) - { - IssueGlobalCommand(GlobalCommands.ToggleProfiling); - } - } - -#if DEBUG - if (InputManager.m_Instance.GetKeyboardShortcutDown( - InputManager.KeyboardShortcut.CheckStrokes)) - { - bool value = !SketchMemoryScript.m_Instance.m_SanityCheckStrokes; - string feature = "Stroke determinism checking"; - SketchMemoryScript.m_Instance.m_SanityCheckStrokes = value; - OutputWindowScript.m_Instance.CreateInfoCardAtController( - InputManager.ControllerName.Brush, - feature + (value ? ": On" : ": Off")); - } -#endif - - bool hasController = m_ControlsType == ControlsType.SixDofControllers; - var mouse = Mouse.current; - - // Toggle default tool. - if (!m_PanelManager.AdvancedModeActive() && - InputManager.m_Instance.GetCommandDown(InputManager.SketchCommands.ToggleDefaultTool) && - !m_SketchSurfacePanel.IsDefaultToolEnabled() && - m_SketchSurfacePanel.ActiveTool.AllowDefaultToolToggle() && - // don't allow tool to change while pointing at panel because there is no visual indication - m_CurrentGazeObject == -1) - { - m_SketchSurfacePanel.EnableDefaultTool(); - AudioManager.m_Instance.PlayPinCushionSound(true); - } - // Pan. - else if (!hasController && mouse.rightButton.isPressed) - { - SwitchState(InputState.Pan); - } - // Controller lock (this must be before rotate/head lock!). - else if (!hasController && - InputManager.m_Instance.GetCommand(InputManager.SketchCommands.LockToController)) - { - SwitchState(InputState.ControllerLock); - } - // Rotate. - else if (!hasController && - InputManager.m_Instance.GetCommand(InputManager.SketchCommands.PivotRotation)) - { - SwitchState(InputState.Rotation); - } - // Head lock. - else if (!hasController && - InputManager.m_Instance.GetCommand(InputManager.SketchCommands.LockToHead)) - { - SwitchState(InputState.HeadLock); - } - // Push pull. - else if (!hasController && - InputManager.m_Instance.GetCommand(InputManager.SketchCommands.AltActivate)) - { - SwitchState(InputState.PushPull); - } - else if (!PointerManager.m_Instance.IsMainPointerCreatingStroke()) - { - // Reset surface. - if (!hasController && - InputManager.m_Instance.GetCommandDown(InputManager.SketchCommands.Reset)) - { - ResetGrabbedPose(); - } - // Undo. - else if (InputManager.m_Instance.GetCommandDown(InputManager.SketchCommands.Undo) && - CanUndo()) - { - IssueGlobalCommand(GlobalCommands.Undo); - } - else if (InputManager.m_Instance.GetCommand(InputManager.SketchCommands.Undo) && - CanUndo() && ShouldRepeatUndo()) - { - m_UndoHold_Timer = m_UndoRedoHold_RepeatInterval; - IssueGlobalCommand(GlobalCommands.Undo); - } - // Redo. - else if (InputManager.m_Instance.GetCommandDown(InputManager.SketchCommands.Redo) && - CanRedo()) - { - IssueGlobalCommand(GlobalCommands.Redo); - } - else if (InputManager.m_Instance.GetCommand(InputManager.SketchCommands.Redo) && - CanRedo() && ShouldRepeatRedo()) - { - m_RedoHold_Timer = m_UndoRedoHold_RepeatInterval; - IssueGlobalCommand(GlobalCommands.Redo); - } - // Reset scene. - else if (!hasController && - InputManager.m_Instance.GetKeyboardShortcutDown( - InputManager.KeyboardShortcut.ResetScene)) - { - // TODO: Should thsi go away? Seems like the "sweetspot" may no longer be used. - if (App.VrSdk.GetControllerDof() == VrSdk.DoF.Two) - { - m_PanelManager.SetSweetSpotPosition(m_CurrentGazeRay.origin); - ResetGrabbedPose(); - } - } - // Straight edge. - else if (!hasController && - InputManager.m_Instance.GetKeyboardShortcutDown( - InputManager.KeyboardShortcut.StraightEdge)) - { - IssueGlobalCommand(GlobalCommands.StraightEdge); - } - // Always fall back on switching tools. - else - { - m_SketchSurfacePanel.CheckForToolSelection(); - } - } - - // Reset undo/redo hold timers. - if (!InputManager.m_Instance.GetCommand(InputManager.SketchCommands.Undo)) - { - m_UndoHold_Timer = m_UndoRedoHold_DurationBeforeStart; - } - if (!InputManager.m_Instance.GetCommand(InputManager.SketchCommands.Redo)) - { - m_RedoHold_Timer = m_UndoRedoHold_DurationBeforeStart; - } - UnityEngine.Profiling.Profiler.EndSample(); - } - - bool CanUndo() - { - return SketchMemoryScript.m_Instance.CanUndo() && - !IsUIBlockingUndoRedo() && - m_PanelManager.GazePanelsAreVisible() && - !m_GrabWand.grabbingWorld && - !InputManager.m_Instance.GetCommand(InputManager.SketchCommands.Activate) && - !SelectionManager.m_Instance.IsAnimatingTossFromGrabbingGroup; - } - - bool CanRedo() - { - return SketchMemoryScript.m_Instance.CanRedo() && - !IsUIBlockingUndoRedo() && - m_PanelManager.GazePanelsAreVisible() && - !m_GrabBrush.grabbingWorld && - !InputManager.m_Instance.GetCommand(InputManager.SketchCommands.Activate) && - !SelectionManager.m_Instance.IsAnimatingTossFromGrabbingGroup; - } - - bool ShouldRepeatUndo() - { - m_UndoHold_Timer -= Time.deltaTime; - return (m_UndoHold_Timer <= 0.0f); - } - - bool ShouldRepeatRedo() - { - m_RedoHold_Timer -= Time.deltaTime; - return (m_RedoHold_Timer <= 0.0f); - } - - // Updates the global state: - // m_CurrentGrabWidget - void UpdateGrab() - { - UnityEngine.Profiling.Profiler.BeginSample("SketchControlScript.UpdateGrab"); - if (m_ControlsType != ControlsType.SixDofControllers) - { - UnityEngine.Profiling.Profiler.EndSample(); - return; - } - - GrabWidget rPrevGrabWidget = m_CurrentGrabWidget; - GrabWidget rPrevPotentialBrush = m_PotentialGrabWidgetBrush; - GrabWidget rPrevPotentialWand = m_PotentialGrabWidgetWand; - if (m_CurrentGrabWidget) - { - m_CurrentGrabWidget.Activate(false); - } - if (m_PotentialGrabWidgetBrush) - { - m_PotentialGrabWidgetBrush.Activate(false); - } - if (m_PotentialGrabWidgetWand) - { - m_PotentialGrabWidgetWand.Activate(false); - } - m_CurrentGrabWidget = null; - m_PotentialGrabWidgetBrush = null; - m_PotentialGrabWidgetWand = null; - m_PotentialGrabWidgetBrushValid = false; - m_PotentialGrabWidgetWandValid = false; - - m_WidgetManager.RefreshNearestWidgetLists(m_CurrentGazeRay, m_CurrentGazeObject); - - if (m_GrabWidgetState == GrabWidgetState.None) - { - UpdateGrab_WasNone(rPrevPotentialBrush, rPrevPotentialWand); - } - else if (m_GrabWidgetState == GrabWidgetState.OneHand) - { - UpdateGrab_WasOneHand(rPrevGrabWidget); - } - else if (m_GrabWidgetState == GrabWidgetState.TwoHands) - { - UpdateGrab_WasTwoHands(rPrevGrabWidget); - } - - // Update grab intersection state. - switch (m_CurrentGrabIntersectionState) - { - case GrabIntersectionState.RequestIntersections: - m_CurrentGrabIntersectionState = GrabIntersectionState.ReadBrush; - break; - case GrabIntersectionState.ReadBrush: - m_CurrentGrabIntersectionState = GrabIntersectionState.ReadWand; - break; - case GrabIntersectionState.ReadWand: - m_CurrentGrabIntersectionState = GrabIntersectionState.RequestIntersections; - break; - } - - if (!TutorialManager.m_Instance.TutorialActive() && m_CurrentGrabWidget == null) - { - UpdateGrab_World(); - } - - App.Instance.SelectionEffect.HighlightForGrab( - m_GrabWidgetState != GrabWidgetState.None || - (m_PotentialGrabWidgetBrush != null && m_PotentialGrabWidgetBrushValid) || - (m_PotentialGrabWidgetWand != null && m_PotentialGrabWidgetWandValid)); - UnityEngine.Profiling.Profiler.EndSample(); - } - - void UpdateGrab_WasNone(GrabWidget rPrevPotentialBrush, GrabWidget rPrevPotentialWand) - { - // if a panel isn't in focus, allow for widget grab - // We can grab a widget as long as we aren't trying to draw with that hand. - bool bActiveInput = - (InputManager.m_Instance.GetCommand(InputManager.SketchCommands.Activate) && - App.Instance.IsInStateThatAllowsPainting()); - - //certain tools don't allow us to mess with widgets - bool bWidgetManipOK = m_SketchSurfacePanel.DoesCurrentToolAllowWidgetManipulation() && - !m_GrabWand.grabbingWorld && !m_GrabBrush.grabbingWorld && IsGrabWorldStateStable() && - App.Instance.IsInStateThatAllowsAnyGrabbing(); - - // Update EatInput flags if they're valid. - if (m_GrabBrush.eatInput) - { - m_GrabBrush.eatInput = InputManager.Brush.GetControllerGrip(); - } - if (m_GrabWand.eatInput) - { - m_GrabWand.eatInput = InputManager.Wand.GetControllerGrip(); - } - - bool bShouldClearWandInside = false; - if (m_CurrentInputState == InputState.Standard && bWidgetManipOK) - { - // If we're in the intersection request state, fire off a new intersection request. If - // we're in the read brush state, update our brush grab data structure. - List brushBests = m_WidgetManager.WidgetsNearBrush; - if (m_CurrentGrabIntersectionState == GrabIntersectionState.RequestIntersections) - { - RequestWidgetIntersection(brushBests, InputManager.ControllerName.Brush); - } - else if (m_CurrentGrabIntersectionState == GrabIntersectionState.ReadBrush) - { - m_BackupBrushGrabData = GetBestWidget(brushBests, m_BrushResults); - } - - if (m_BackupBrushGrabData != null) - { - m_PotentialGrabWidgetBrush = m_BackupBrushGrabData.m_WidgetScript; - - // Allow widget grab if we're not painting. - if (!bActiveInput) - { - m_PotentialGrabWidgetBrush.Activate(true); - m_PotentialGrabWidgetBrushValid = true; - m_PotentialGrabWidgetBrush.VisualizePinState(); - - if (!m_GrabBrush.eatInput && InputManager.Brush.GetControllerGrip()) - { - m_CurrentGrabWidget = m_PotentialGrabWidgetBrush; - if (m_CurrentGrabWidget.Group != SketchGroupTag.None) - { - m_GrabBrush.grabbingGroup = true; - m_CurrentGrabWidget = - SelectionManager.m_Instance.StartGrabbingGroupWithWidget(m_CurrentGrabWidget); - } - UpdateGrab_NoneToOne(InputManager.ControllerName.Brush); - bShouldClearWandInside = true; - m_GrabBrush.startedGrabInsideWidget = true; - } - } - } - m_GrabBrush.SetHadBestGrabAndTriggerHaptics(m_BackupBrushGrabData); - m_ControllerGrabVisuals.BrushInWidgetRange = m_BackupBrushGrabData != null; - - // If we're in the intersection request state, fire off a new intersection request. If - // we're in the read wand state, update our wand grab data structure. - List wandBests = m_WidgetManager.WidgetsNearWand; - if (m_CurrentGrabIntersectionState == GrabIntersectionState.RequestIntersections) - { - RequestWidgetIntersection(wandBests, InputManager.ControllerName.Wand); - } - else if (m_CurrentGrabIntersectionState == GrabIntersectionState.ReadWand) - { - m_BackupWandGrabData = GetBestWidget(wandBests, m_WandResults); - } - - if (m_BackupWandGrabData != null) - { - m_PotentialGrabWidgetWand = m_BackupWandGrabData.m_WidgetScript; - // Allow wand widget grab if brush grab failed. - bool bGrabAllowed = (m_GrabWidgetState == GrabWidgetState.None) && !bActiveInput; - if (bGrabAllowed) - { - m_PotentialGrabWidgetWand.Activate(true); - m_PotentialGrabWidgetWandValid = true; - m_PotentialGrabWidgetWand.VisualizePinState(); - - if (!m_GrabWand.eatInput && InputManager.Wand.GetControllerGrip()) - { - m_CurrentGrabWidget = m_PotentialGrabWidgetWand; - if (m_CurrentGrabWidget.Group != SketchGroupTag.None) - { - m_GrabWand.grabbingGroup = true; - m_CurrentGrabWidget = - SelectionManager.m_Instance.StartGrabbingGroupWithWidget(m_CurrentGrabWidget); - } - UpdateGrab_NoneToOne(InputManager.ControllerName.Wand); - m_GrabBrush.ClearInsideWidget(); - m_GrabWand.startedGrabInsideWidget = true; - } - } - } - m_GrabWand.SetHadBestGrabAndTriggerHaptics(m_BackupWandGrabData); - m_ControllerGrabVisuals.WandInWidgetRange = m_BackupWandGrabData != null; - - // Account for asymmetry in controller processing by clearing after wand has updated - // GrabState.insideWidget according to bestWandGrab. - if (bShouldClearWandInside) - { - m_GrabWand.ClearInsideWidget(); - } - } - - // Update widget collisions if we've got a drifter. - if (m_GrabWidgetState == GrabWidgetState.None) - { - if (m_WidgetManager.ShouldUpdateCollisions()) - { - m_PanelManager.DoCollisionSimulationForWidgetPanels(); - } - } - } - - void UpdateGrab_WasOneHand(GrabWidget rPrevGrabWidget) - { - var controller = InputManager.Controllers[(int)m_GrabWidgetOneHandInfo.m_Name]; - bool shouldRelease = !App.Instance.IsInStateThatAllowsAnyGrabbing(); - if (!InputManager.Controllers[(int)m_GrabWidgetOneHandInfo.m_Name].GetControllerGrip() || - shouldRelease) - { - if (shouldRelease) - { - EatGrabInput(); - } - - Vector3 vLinearVelocity; - Vector3 vAngularVelocity; - if (GetGrabWidgetHoldHistory(out vLinearVelocity, out vAngularVelocity)) - { - rPrevGrabWidget.SetVelocities( - vLinearVelocity, vAngularVelocity, - controller.Transform.position); - } - // One -> None - UpdateGrab_ToNone(rPrevGrabWidget); - } - else - { - // Keep holding on to our widget. - m_CurrentGrabWidget = rPrevGrabWidget; - m_CurrentGrabWidget.Activate(true); - m_CurrentGrabWidget.UserInteracting(true, m_GrabWidgetOneHandInfo.m_Name); - - if (!m_CurrentGrabWidget.Pinned) - { - var info = InputManager.Controllers[(int)m_GrabWidgetOneHandInfo.m_Name]; - var controllerXf = Coords.AsGlobal[info.Transform]; - var newWidgetXf = controllerXf * m_GrabWidgetOneHandInfo.m_BaseWidgetXf_LS; - m_CurrentGrabWidget.RecordAndSetPosRot(newWidgetXf); - - UpdateGrabWidgetHoldHistory(m_GrabWidgetOneHandInfo.m_Name); - } - - m_PanelManager.DoCollisionSimulationForWidgetPanels(); - - // Check for widget pinning. - if (m_CurrentGrabWidget.AllowPinning) - { - if (InputManager.Controllers[(int)m_GrabWidgetOneHandInfo.m_Name].GetCommandDown( - InputManager.SketchCommands.PinWidget)) - { - // If the user initiates a pin action, buzz a bit. - if (!m_CurrentGrabWidget.Pinned) - { - InputManager.m_Instance.TriggerHapticsPulse( - m_GrabWidgetOneHandInfo.m_Name, 3, 0.10f, 0.07f); - } - m_CurrentGrabWidget.Pin(!m_CurrentGrabWidget.Pinned); - SketchSurfacePanel.m_Instance.EatToolsInput(); - m_WidgetManager.RefreshPinAndUnpinLists(); - } - } - - if (m_CurrentGrabWidget is SelectionWidget) - { - if (InputManager.m_Instance.GetCommandDown( - InputManager.SketchCommands.DuplicateSelection)) - { - controller.LastHeldInput = - controller.GetCommandHoldInput(InputManager.SketchCommands.DuplicateSelection); - } - - if (controller.LastHeldInput != null && - InputManager.m_Instance.GetCommandHeld(InputManager.SketchCommands.DuplicateSelection)) - { - SketchControlsScript.m_Instance.IssueGlobalCommand( - SketchControlsScript.GlobalCommands.Duplicate); - } - } - - InputManager.ControllerName otherName = - (m_GrabWidgetOneHandInfo.m_Name == InputManager.ControllerName.Brush) ? - InputManager.ControllerName.Wand : InputManager.ControllerName.Brush; - bool otherInputEaten = - (m_GrabWidgetOneHandInfo.m_Name == InputManager.ControllerName.Brush) ? - m_GrabWand.eatInput : m_GrabBrush.eatInput; - - // See if the other controller decides to grab the widget (unless we're pinned). - if (!m_CurrentGrabWidget.Pinned) - { - if (m_CurrentGrabWidget.AllowTwoHandGrab) - { - if (InputManager.Controllers[(int)otherName].GetControllerGrip()) - { - RequestPanelsVisibility(false); - m_GrabWidgetState = GrabWidgetState.TwoHands; - // Figure out if the new grab starts inside the widget. - Vector3 vOtherGrabPos = TrTransform.FromTransform( - InputManager.m_Instance.GetController(otherName)).translation; - bool bOtherGrabInBounds = m_CurrentGrabWidget.GetActivationScore( - vOtherGrabPos, otherName) >= 0; - m_CurrentGrabWidget.SetUserTwoHandGrabbing( - true, m_GrabWidgetOneHandInfo.m_Name, otherName, bOtherGrabInBounds); - - if (otherName == InputManager.ControllerName.Brush) - { - m_GrabBrush.startedGrabInsideWidget = bOtherGrabInBounds; - } - else - { - m_GrabWand.startedGrabInsideWidget = bOtherGrabInBounds; - } - - m_GrabWidgetTwoHandBrushPrev = TrTransform.FromTransform( - InputManager.m_Instance.GetController(InputManager.ControllerName.Brush)); - m_GrabWidgetTwoHandWandPrev = TrTransform.FromTransform( - InputManager.m_Instance.GetController(InputManager.ControllerName.Wand)); - } - } - } - else if (!otherInputEaten && InputManager.Controllers[(int)otherName].GetControllerGrip()) - { - // If it's a two hand grab but the current grab widget is pinned, grab the world. - UpdateGrab_ToNone(m_CurrentGrabWidget); - m_CurrentGrabWidget = null; - m_ControllerGrabVisuals.SetDesiredVisualState(ControllerGrabVisuals.VisualState.Off); - } - } - } - - // Previous frame was a two-handed grab. - // Handles all the cases where this frame's grab is zero, one, or two hands. - void UpdateGrab_WasTwoHands(GrabWidget rPrevGrabWidget) - { - //keep holding on to our widget - m_CurrentGrabWidget = rPrevGrabWidget; - m_CurrentGrabWidget.Activate(true); - m_CurrentGrabWidget.UserInteracting(true, m_GrabWidgetOneHandInfo.m_Name); - - if (!App.Instance.IsInStateThatAllowsAnyGrabbing()) - { - m_CurrentGrabWidget.SetUserTwoHandGrabbing(false); - UpdateGrab_ToNone(rPrevGrabWidget); - } - else if (!InputManager.Wand.GetControllerGrip()) - { // Look for button release. - m_CurrentGrabWidget.SetUserTwoHandGrabbing(false); - // See if our Brush hand is still within grab range of the widget. - if (m_GrabBrush.startedGrabInsideWidget || - IsControllerNearWidget(InputManager.ControllerName.Brush, m_CurrentGrabWidget)) - { - m_GrabWidgetOneHandInfo.m_Name = InputManager.ControllerName.Brush; - RequestPanelsVisibility(true); - InitializeGrabWidgetControllerInfo(m_GrabWidgetOneHandInfo); - m_GrabWidgetState = GrabWidgetState.OneHand; - } - else - { - // If the Brush hand is beyond the widget, we're not holding it anymore. - UpdateGrab_ToNone(rPrevGrabWidget); - - // Eat input on the brush grip until we release the button. - m_GrabBrush.eatInput = true; - } - } - else if (!InputManager.Brush.GetControllerGrip()) - { - m_CurrentGrabWidget.SetUserTwoHandGrabbing(false); - if (m_GrabWand.startedGrabInsideWidget || - IsControllerNearWidget(InputManager.ControllerName.Wand, m_CurrentGrabWidget)) - { - m_GrabWidgetOneHandInfo.m_Name = InputManager.ControllerName.Wand; - InitializeGrabWidgetControllerInfo(m_GrabWidgetOneHandInfo); - m_GrabWidgetState = GrabWidgetState.OneHand; - } - else - { - UpdateGrab_ToNone(rPrevGrabWidget); - m_GrabWand.eatInput = true; - } - } - else - { - // Both hands still grabbing. - // Check for pin, which forcibly releases one of the hands. - if (m_CurrentGrabWidget.AllowPinning && - InputManager.Controllers[(int)m_GrabWidgetOneHandInfo.m_Name].GetCommandDown( - InputManager.SketchCommands.PinWidget)) - { - // If the user initiates a pin action, buzz a bit. - if (!m_CurrentGrabWidget.Pinned) - { - InputManager.m_Instance.TriggerHapticsPulse( - m_GrabWidgetOneHandInfo.m_Name, 3, 0.10f, 0.07f); - } - - m_CurrentGrabWidget.Pin(!m_CurrentGrabWidget.Pinned); - SketchSurfacePanel.m_Instance.EatToolsInput(); - m_WidgetManager.RefreshPinAndUnpinLists(); - - InitializeGrabWidgetControllerInfo(m_GrabWidgetOneHandInfo); - m_GrabWidgetState = GrabWidgetState.OneHand; - m_CurrentGrabWidget.SetUserTwoHandGrabbing(false); - - // Eat input on the off hand so we don't immediately jump in to world transform. - if (m_GrabWidgetOneHandInfo.m_Name == InputManager.ControllerName.Brush) - { - RequestPanelsVisibility(true); - m_GrabWand.eatInput = true; - } - else - { - m_GrabBrush.eatInput = true; - } - } - - if (!m_CurrentGrabWidget.Pinned) - { - UpdateGrab_ContinuesTwoHands(); - } - } - ClearGrabWidgetHoldHistory(); - m_PanelManager.DoCollisionSimulationForWidgetPanels(); - } - - // Common case for two-handed grab: both the previous and current frames are two-handed. - private void UpdateGrab_ContinuesTwoHands() - { - //holding with two hands, transform accordingly - TrTransform xfBrush = TrTransform.FromTransform(InputManager.Brush.Transform); - TrTransform xfWand = TrTransform.FromTransform(InputManager.Wand.Transform); - Vector2 vSizeRange = m_CurrentGrabWidget.GetWidgetSizeRange(); - - GrabWidget.Axis axis = m_CurrentGrabWidget.GetScaleAxis( - xfWand.translation, xfBrush.translation, - out Vector3 axisDirection, out float axisExtent); - - TrTransform newWidgetXf; - if (axis != GrabWidget.Axis.Invalid) - { - // Scale along a single axis - float deltaScale; - if (App.Config.m_AxisManipulationIsResize) - { - newWidgetXf = MathUtils.TwoPointObjectTransformationAxisResize( - axisDirection, axisExtent, - m_GrabWidgetTwoHandWandPrev, m_GrabWidgetTwoHandBrushPrev, - xfWand, xfBrush, - GetWorkingTransform(m_CurrentGrabWidget), - out deltaScale, - deltaScaleMin: vSizeRange.x / axisExtent, - deltaScaleMax: vSizeRange.y / axisExtent); - } - else - { - newWidgetXf = MathUtils.TwoPointObjectTransformationNonUniformScale( - axisDirection, - m_GrabWidgetTwoHandWandPrev, m_GrabWidgetTwoHandBrushPrev, - xfWand, xfBrush, - GetWorkingTransform(m_CurrentGrabWidget), - out deltaScale, - finalScaleMin: vSizeRange.x, - deltaScaleMin: vSizeRange.x / axisExtent, - deltaScaleMax: vSizeRange.y / axisExtent); - } - - // The above functions return undefined values in newWidgetXf.scale; but that's - // okay because RecordAndSetPosRot ignores xf.scale. - // TODO: do this more cleanly - m_CurrentGrabWidget.RecordAndApplyScaleToAxis(deltaScale, axis); - } - else - { - // Uniform scaling - TrTransform xfObject = GetWorkingTransform(m_CurrentGrabWidget); - Vector3 extents = (m_CurrentGrabWidget is StencilWidget) - ? (m_CurrentGrabWidget as StencilWidget).Extents - : Vector3.one * Mathf.Abs(m_CurrentGrabWidget.GetSignedWidgetSize()); - - // Delta-scale bounds should be based on the smallest/largest extent. - // Irritatingly, the API wants absolute rather than relative scale bounds, - // so they need even more conversion. - float deltaScaleMin = vSizeRange.x / extents.Min(); - float deltaScaleMax = vSizeRange.y / extents.Max(); - if (m_GrabWand.startedGrabInsideWidget && m_GrabBrush.startedGrabInsideWidget) - { - newWidgetXf = MathUtils.TwoPointObjectTransformation( - m_GrabWidgetTwoHandWandPrev, m_GrabWidgetTwoHandBrushPrev, - xfWand, xfBrush, - xfObject, - deltaScaleMin: deltaScaleMin, deltaScaleMax: deltaScaleMax); - } - else if (m_GrabWand.startedGrabInsideWidget) - { - // keep the wand inside the object - newWidgetXf = MathUtils.TwoPointObjectTransformation( - m_GrabWidgetTwoHandWandPrev, m_GrabWidgetTwoHandBrushPrev, - xfWand, xfBrush, - xfObject, - deltaScaleMin: deltaScaleMin, deltaScaleMax: deltaScaleMax, - bUseLeftAsPivot: true); - } - else - { - // keep the brush inside the object (note the brush is the left hand) - newWidgetXf = MathUtils.TwoPointObjectTransformation( - m_GrabWidgetTwoHandBrushPrev, m_GrabWidgetTwoHandWandPrev, - xfBrush, xfWand, - xfObject, - deltaScaleMin: deltaScaleMin, deltaScaleMax: deltaScaleMax, - bUseLeftAsPivot: true); - } - - // Must do separately becvause RecordAndSetPosRot ignores newWidgetXf.scale - m_CurrentGrabWidget.RecordAndSetSize(newWidgetXf.scale); - - float currentSize = Mathf.Abs(m_CurrentGrabWidget.GetSignedWidgetSize()); - if (currentSize == vSizeRange.x || currentSize == vSizeRange.y) - { - InputManager.m_Instance.TriggerHaptics(InputManager.ControllerName.Brush, 0.05f); - InputManager.m_Instance.TriggerHaptics(InputManager.ControllerName.Wand, 0.05f); - } - } - - // Ignores TrTransform.scale - m_CurrentGrabWidget.RecordAndSetPosRot(newWidgetXf); - - m_GrabWidgetTwoHandBrushPrev = xfBrush; - m_GrabWidgetTwoHandWandPrev = xfWand; - } - - void UpdateGrab_NoneToOne(InputManager.ControllerName controllerName) - { - if (m_MaybeDriftingGrabWidget != null && - m_MaybeDriftingGrabWidget.IsMoving() && - !m_MaybeDriftingGrabWidget.IsSpinningFreely) - { - // If a new widget is grabbed but the previous one is still drifting, end the drift. - // TODO: Simplify in the widget animation cleanup. - if (m_MaybeDriftingGrabWidget == m_CurrentGrabWidget) - { - SketchMemoryScript.m_Instance.PerformAndRecordCommand( - new MoveWidgetCommand(m_MaybeDriftingGrabWidget, - m_MaybeDriftingGrabWidget.LocalTransform, m_MaybeDriftingGrabWidget.CustomDimension, - final: true), - discardIfNotMerged: true); - } - m_MaybeDriftingGrabWidget.ClearVelocities(); - } - - // UserInteracting should be the first thing that happens here so OnUserBeginInteracting can - // be called before everything else. - m_CurrentGrabWidget.UserInteracting(true, controllerName); - m_CurrentGrabWidget.ClearVelocities(); - ClearGrabWidgetHoldHistory(); - - //set our info names according to this controller's name - m_GrabWidgetOneHandInfo.m_Name = controllerName; - InitializeGrabWidgetControllerInfo(m_GrabWidgetOneHandInfo); - - PointerManager.m_Instance.AllowPointerPreviewLine(false); - PointerManager.m_Instance.RequestPointerRendering(false); - m_SketchSurfacePanel.RequestHideActiveTool(true); - if (m_GrabWidgetOneHandInfo.m_Name == InputManager.ControllerName.Wand) - { - RequestPanelsVisibility(false); - } - - // Notify visuals. - ControllerGrabVisuals.VisualState visualState = - m_GrabWidgetOneHandInfo.m_Name == InputManager.ControllerName.Brush ? - ControllerGrabVisuals.VisualState.WidgetBrushGrip : - ControllerGrabVisuals.VisualState.WidgetWandGrip; - m_ControllerGrabVisuals.SetDesiredVisualState(visualState); - m_ControllerGrabVisuals.SetHeldWidget(m_CurrentGrabWidget.transform); - - //if a gaze object had focus when we grabbed this widget, take focus off the object - ResetActivePanel(); - m_UIReticle.SetActive(false); - - // Prep all other grab widgets for collision. - m_PanelManager.PrimeCollisionSimForWidgets(m_CurrentGrabWidget); - - m_GrabWidgetState = GrabWidgetState.OneHand; - m_WidgetManager.WidgetsDormant = false; - PointerManager.m_Instance.EatLineEnabledInput(); - - m_BackupWandGrabData = null; - m_BackupBrushGrabData = null; - } - - void UpdateGrab_ToNone(GrabWidget rPrevGrabWidget) - { - m_MaybeDriftingGrabWidget = rPrevGrabWidget; - - m_GrabWidgetState = GrabWidgetState.None; - PointerManager.m_Instance.RequestPointerRendering(!App.Instance.IsLoading() && - m_SketchSurfacePanel.ShouldShowPointer()); - RequestPanelsVisibility(true); - m_SketchSurfacePanel.RequestHideActiveTool(false); - rPrevGrabWidget.UserInteracting(false); - - // Disable grab visuals. - m_ControllerGrabVisuals.SetDesiredVisualState(ControllerGrabVisuals.VisualState.Off); - m_ControllerGrabVisuals.SetHeldWidget(null); - - if (m_GrabBrush.grabbingGroup || m_GrabWand.grabbingGroup) - { - SelectionManager.m_Instance.EndGrabbingGroupWithWidget(); - m_GrabBrush.grabbingGroup = false; - m_GrabWand.grabbingGroup = false; - } - } - - void RequestWidgetIntersection(List candidates, - InputManager.ControllerName controllerName) - { - // Get locals based off what controller we're using. - Queue resultQueue = null; - Vector3 controllerPos = Vector3.zero; - if (controllerName == InputManager.ControllerName.Brush) - { - resultQueue = m_BrushResults; - controllerPos = InputManager.m_Instance.GetBrushControllerAttachPoint().position; - } - else - { - resultQueue = m_WandResults; - controllerPos = InputManager.m_Instance.GetWandControllerAttachPoint().position; - } - - // If we don't have a candidate that has a GPU object, don't bother firing off a GPU request. - bool requestGpuIntersection = false; - - // Fire off a new GPU intersection with all widgets that can use it. - for (int i = 0; i < candidates.Count; ++i) - { - if (candidates[i].m_WidgetScript.HasGPUIntersectionObject()) - { - candidates[i].m_WidgetScript.SetGPUIntersectionObjectLayer(m_WidgetGpuIntersectionLayer); - requestGpuIntersection = true; - } - } - - if (requestGpuIntersection) - { - GpuIntersectionResult newRequest = new GpuIntersectionResult(); - newRequest.resultList = new List(); - newRequest.result = App.Instance.GpuIntersector.RequestModelIntersections( - controllerPos, m_WidgetGpuIntersectionRadius, newRequest.resultList, 8, - (1 << m_WidgetGpuIntersectionLayer)); - - // The new result will only be null when the intersector is disabled. - if (newRequest.result != null) - { - resultQueue.Enqueue(newRequest); - } - - for (int i = 0; i < candidates.Count; ++i) - { - if (candidates[i].m_WidgetScript.HasGPUIntersectionObject()) - { - candidates[i].m_WidgetScript.RestoreGPUIntersectionObjectLayer(); - } - } - } - } - - GrabWidgetData GetBestWidget(List candidates, - Queue resultQueue) - { - // Discard futures that are too old. - while (resultQueue.Count > 0) - { - if (Time.frameCount - resultQueue.Peek().result.StartFrame < 5) - { - break; - } - resultQueue.Dequeue(); - } - - // If the oldest future is ready, use its intersection result to update the candidates. - GpuIntersectionResult finishedResult; - if (resultQueue.Count > 0 && resultQueue.Peek().result.IsReady) - { - finishedResult = resultQueue.Dequeue(); - } - else - { - finishedResult.resultList = new List(); - } - - // TODO: Speed this up. - for (int i = 0; i < candidates.Count; ++i) - { - if (candidates[i].m_WidgetScript.HasGPUIntersectionObject()) - { - // If a candidate can't find itself in the finished results list, it's not eligible. - bool candidateValid = false; - for (int j = 0; j < finishedResult.resultList.Count; ++j) - { - if (candidates[i].m_WidgetScript.Equals(finishedResult.resultList[j].widget)) - { - candidateValid = true; - break; - } - } - - if (candidateValid) - { - // If a candidate has a GPU intersection object and we found it in this list, - // not only is it valid, but it's as valid as it can be. - candidates[i].m_ControllerScore = 1.0f; - } - else - { - candidates[i].m_NearController = false; - } - } - } - - // Run through the candidates and pick - GrabWidgetData best = null; - for (int i = 0; i < candidates.Count; ++i) - { - var candidate = candidates[i]; - if (!candidate.m_NearController) continue; - - // For media widgets - only select from the active layer - if (candidate.m_WidgetScript is MediaWidget - && candidate.m_WidgetScript.Canvas != App.Scene.ActiveCanvas) continue; - - if (best == null || candidate.m_ControllerScore > best.m_ControllerScore) - { - best = candidate; - } - } - return best; - } - - void InitializeGrabWidgetControllerInfo(GrabWidgetControllerInfo info) - { - Transform controller = InputManager.Controllers[(int)info.m_Name].Transform; - Transform widget = m_CurrentGrabWidget.GrabTransform_GS; - TrTransform newWidgetXf = Coords.AsGlobal[widget]; - - info.m_BaseControllerXf = Coords.AsGlobal[controller]; - info.m_BaseWidgetXf_LS = info.m_BaseControllerXf.inverse * newWidgetXf; - } - - // returns the transform of the true widget (not the snapped one for those that can be) - private TrTransform GetWorkingTransform(GrabWidget w) - { - TrTransform ret = w.GetGrabbedTrTransform(); - ret.scale = w.GetSignedWidgetSize(); - return ret; - } - - // Initiate the world transform reset animation. - public void RequestWorldTransformReset(bool toSavedXf = false) - { - if (WorldIsReset(toSavedXf)) - { - return; - } - - m_WorldTransformResetXf = - toSavedXf ? SketchMemoryScript.m_Instance.InitialSketchTransform : TrTransform.identity; - m_WorldTransformResetState = WorldTransformResetState.Requested; - - App.Scene.disableTiltProtection = false; - } - - void UpdateWorldTransformReset() - { - switch (m_WorldTransformResetState) - { - case WorldTransformResetState.Requested: - ViewpointScript.m_Instance.FadeToColor(Color.black, m_GrabWorldFadeSpeed); - m_WorldTransformResetState = WorldTransformResetState.FadingToBlack; - m_xfDropCamReset_RS = Coords.AsRoom[m_DropCam.transform]; - PointerManager.m_Instance.EatLineEnabledInput(); - PointerManager.m_Instance.AllowPointerPreviewLine(false); - break; - case WorldTransformResetState.FadingToBlack: - m_WorldTransformFadeAmount += m_GrabWorldFadeSpeed * Time.deltaTime; - if (m_WorldTransformFadeAmount >= 1.0f) - { - App.Scene.Pose = m_WorldTransformResetXf; - m_WorldTransformFadeAmount = 1.0f; - m_WorldTransformResetState = WorldTransformResetState.FadingToScene; - ViewpointScript.m_Instance.FadeToScene(m_GrabWorldFadeSpeed); - m_DropCam.transform.position = m_xfDropCamReset_RS.translation; - m_DropCam.transform.rotation = m_xfDropCamReset_RS.rotation; - PointerManager.m_Instance.AllowPointerPreviewLine(true); - } - break; - case WorldTransformResetState.FadingToScene: - m_WorldTransformFadeAmount -= m_GrabWorldFadeSpeed * Time.deltaTime; - if (m_WorldTransformFadeAmount <= 0.0f) - { - m_WorldTransformFadeAmount = 0.0f; - m_WorldTransformResetState = WorldTransformResetState.Default; - } - break; - } - } - - bool CheckToggleTiltProtection() - { - if ( - InputManager.Wand.GetCommandDown(InputManager.SketchCommands.Redo) || - InputManager.Brush.GetCommandDown(InputManager.SketchCommands.Redo) - ) - { - App.Scene.disableTiltProtection = !App.Scene.disableTiltProtection; - - return !App.Scene.disableTiltProtection; - } - - return false; - - } - - void UpdateGrab_World() - { - bool bAllowWorldTransform = m_SketchSurfacePanel.ActiveTool.AllowWorldTransformation() && - (m_GrabWorldState != GrabWorldState.ResetDone) && - (!PointerManager.m_Instance.IsMainPointerCreatingStroke() || App.Instance.IsLoading()) && - App.Instance.IsInStateThatAllowsAnyGrabbing() && - !m_DisableWorldGrabbing; - - bool bWorldGrabWandPrev = m_GrabWand.grabbingWorld; - bool bWorldGrabBrushPrev = m_GrabBrush.grabbingWorld; - m_GrabWand.grabbingWorld = bAllowWorldTransform && !m_GrabWand.eatInput && - InputManager.Wand.GetControllerGrip(); - m_GrabBrush.grabbingWorld = bAllowWorldTransform && !m_GrabBrush.eatInput && - InputManager.Brush.GetControllerGrip() && - (m_CurrentGazeObject == -1); - - bool grabsChanged = (bWorldGrabWandPrev != m_GrabWand.grabbingWorld) || - (bWorldGrabBrushPrev != m_GrabBrush.grabbingWorld); - bool bAllowWorldTransformChanged = - bAllowWorldTransform != m_AllowWorldTransformLastFrame; - int nGrabs = m_GrabWand.grabbingWorld ? 1 : 0; - nGrabs += m_GrabBrush.grabbingWorld ? 1 : 0; - - // Allow grabbing again if grabs have changed and we're done resetting. - if (m_GrabWorldState == GrabWorldState.ResetDone && grabsChanged) - { - m_GrabWorldState = GrabWorldState.Normal; - } - - // Update panels visibility if brush grip has changed. - if (bWorldGrabWandPrev != m_GrabWand.grabbingWorld) - { - RequestPanelsVisibility(!m_GrabWand.grabbingWorld); - } - - // Update tool visibility if brush grip has changed. - if (bWorldGrabBrushPrev != m_GrabBrush.grabbingWorld) - { - m_SketchSurfacePanel.RequestHideActiveTool(m_GrabBrush.grabbingWorld); - PointerManager.m_Instance.AllowPointerPreviewLine(!m_GrabBrush.grabbingWorld); - PointerManager.m_Instance.RequestPointerRendering(!m_GrabBrush.grabbingWorld - && m_SketchSurfacePanel.ShouldShowPointer() && !App.Instance.IsLoading()); - } - - // Reset m_WorldBeingGrabbed and only set it when world is actually being grabbed. - bool bWorldBeingGrabbedPrev = m_WorldBeingGrabbed; - m_WorldBeingGrabbed = false; - - // Move the world if it has been grabbed. - if (m_GrabWorldState == GrabWorldState.Normal && bAllowWorldTransform) - { - if (nGrabs == 2) - { - // Two-handed world movement. - m_WorldBeingGrabbed = true; - TrTransform grabXfWand = TrTransform.FromTransform( - InputManager.m_Instance.GetController(InputManager.ControllerName.Wand)); - TrTransform grabXfBrush = TrTransform.FromTransform( - InputManager.m_Instance.GetController(InputManager.ControllerName.Brush)); - - // Offset the controller positions so that they're centered on the grips. - Vector3 gripPos = InputManager.Controllers[(int)InputManager.ControllerName.Brush].Geometry.GripAttachPoint.localPosition; - gripPos.x = 0.0f; - grabXfWand.translation += grabXfWand.MultiplyVector(gripPos); - grabXfBrush.translation += grabXfBrush.MultiplyVector(gripPos); - - // Are we initiating two hand transform this frame? - if (!bWorldGrabWandPrev || !bWorldGrabBrushPrev) - { - PointerManager.m_Instance.EnableLine(false); - PointerManager.m_Instance.AllowPointerPreviewLine(false); - PointerManager.m_Instance.RequestPointerRendering(false); - // Initiate audio loop - m_WorldTransformSpeedSmoothed = 0.0f; - AudioManager.m_Instance.WorldGrabLoop(true); - } - else - { - TrTransform xfOld = GrabbedPose; - TrTransform xfNew; - float deltaScaleMin = WorldTransformMinScale / xfOld.scale; - float deltaScaleMax = WorldTransformMaxScale / xfOld.scale; - bool fixOffset = false; - fixOffset = CheckToggleTiltProtection(); - xfNew = MathUtils.TwoPointObjectTransformation( - m_GrabBrush.grabTransform, m_GrabWand.grabTransform, - grabXfBrush, grabXfWand, - xfOld, - rotationAxisConstraint: (App.Scene.disableTiltProtection ? default(Vector3) : Vector3.up), - deltaScaleMin: deltaScaleMin, deltaScaleMax: deltaScaleMax); - float fCurrentWorldTransformSpeed = - Mathf.Abs((xfNew.scale - xfOld.scale) / Time.deltaTime); - m_WorldTransformSpeedSmoothed = - Mathf.Lerp(m_WorldTransformSpeedSmoothed, fCurrentWorldTransformSpeed, - AudioManager.m_Instance.m_WorldGrabLoopSmoothSpeed * Time.deltaTime); - AudioManager.m_Instance.ChangeLoopVolume("WorldGrab", - Mathf.Clamp(m_WorldTransformSpeedSmoothed / - AudioManager.m_Instance.m_WorldGrabLoopAttenuation, 0f, - AudioManager.m_Instance.m_WorldGrabLoopMaxVolume)); - - if (fixOffset) - { - Vector3 midPoint = Vector3.Lerp(grabXfBrush.translation, grabXfWand.translation, 0.5f); - - Vector3 localMidPointOldXF = xfOld.inverse * midPoint; - - // assign this to force the axial protection - GrabbedPose = xfNew; - xfNew = GrabbedPose; - - Vector3 midPointXFNew = xfNew * localMidPointOldXF; - - TrTransform xfDelta1 = TrTransform.T(midPoint - midPointXFNew); - xfNew = xfDelta1 * xfNew; - } - GrabbedPose = xfNew; - } - - // Update last states. - m_GrabBrush.grabTransform = grabXfBrush; - m_GrabWand.grabTransform = grabXfWand; - } - } - else if (m_GrabWorldState == GrabWorldState.ResettingTransform) - { - if (m_WorldTransformResetState == WorldTransformResetState.FadingToScene) - { - ResetGrabbedPose(); - PanelManager.m_Instance.ExecuteOnPanel(x => x.OnPanelMoved()); - - // World can't be transformed right after a reset until grab states have changed. - if (bAllowWorldTransform) - { - bAllowWorldTransform = false; - bAllowWorldTransformChanged = - bAllowWorldTransform != m_AllowWorldTransformLastFrame; - } - - // Set the grab world state on exit. - if (nGrabs == 0) - { - m_GrabWorldState = GrabWorldState.Normal; - } - else - { - m_GrabWorldState = GrabWorldState.ResetDone; - } - } - } - - if (grabsChanged || bAllowWorldTransformChanged) - { - // Fade in grid when doing two handed spin. - if (nGrabs == 2 && !bAllowWorldTransformChanged) - { - ViewpointScript.m_Instance.FadeGroundPlaneIn(m_GrabWorldGridColor, m_GrabWorldFadeSpeed); - } - else - { - ViewpointScript.m_Instance.FadeGroundPlaneOut(m_GrabWorldFadeSpeed); - } - } - - // Update visuals for world transform - if (grabsChanged) - { - bool bDoubleGrip = m_GrabBrush.grabbingWorld && m_GrabWand.grabbingWorld; - bool bSingleGrip = m_GrabBrush.grabbingWorld || m_GrabWand.grabbingWorld; - Vector3 vControllersMidpoint = - (InputManager.m_Instance.GetControllerPosition(InputManager.ControllerName.Brush) + - InputManager.m_Instance.GetControllerPosition(InputManager.ControllerName.Wand)) * 0.5f; - - // Update transform line visuals - if (bDoubleGrip) - { - m_ControllerGrabVisuals.SetDesiredVisualState(ControllerGrabVisuals.VisualState.WorldDoubleGrip); - AudioManager.m_Instance.WorldGrabbed(vControllersMidpoint); - } - else if (bSingleGrip) - { - if (m_GrabWand.grabbingWorld) - { - m_ControllerGrabVisuals.SetDesiredVisualState(ControllerGrabVisuals.VisualState.WorldWandGrip); - } - else - { - m_ControllerGrabVisuals.SetDesiredVisualState(ControllerGrabVisuals.VisualState.WorldBrushGrip); - } - - if (!bWorldGrabWandPrev && !bWorldGrabBrushPrev) - { - AudioManager.m_Instance.WorldGrabbed(vControllersMidpoint); - } - else - { - AudioManager.m_Instance.WorldGrabLoop(false); - } - } - else - { - m_ControllerGrabVisuals.SetDesiredVisualState(ControllerGrabVisuals.VisualState.Off); - AudioManager.m_Instance.WorldGrabLoop(false); - } - - if (m_GrabWand.grabbingWorld || m_GrabBrush.grabbingWorld) - { - m_WidgetManager.WidgetsDormant = false; - PointerManager.m_Instance.EatLineEnabledInput(); - } - } - - // Reset scene transform if we're gripping and press the track pad. - bool wandReset = m_GrabWand.grabbingWorld && - InputManager.Wand.GetCommandDown(InputManager.SketchCommands.WorldTransformReset); - bool brushReset = m_GrabBrush.grabbingWorld && - InputManager.Brush.GetCommandDown(InputManager.SketchCommands.WorldTransformReset); - if ((wandReset || brushReset) && !WorldIsReset(toSavedXf: false)) - { - m_GrabBrush.eatInput = true; - m_GrabWand.eatInput = true; - m_EatToolScaleInput = true; - m_GrabWorldState = GrabWorldState.ResettingTransform; - RequestWorldTransformReset(); - AudioManager.m_Instance.PlayTransformResetSound(); - } - - // Update the skybox rotation with the new scene rotation. - if (RenderSettings.skybox) - { - Quaternion sceneQuaternion = App.Instance.m_SceneTransform.rotation; - RenderSettings.skybox.SetVector( - "_SkyboxRotation", - new Vector4(sceneQuaternion.x, sceneQuaternion.y, sceneQuaternion.z, sceneQuaternion.w)); - } - - // Update last frame members. - m_AllowWorldTransformLastFrame = bAllowWorldTransform; - } - - /// If lhs and rhs are overlapping, return the smallest vector that would - /// cause rhs to stop overlapping; otherwise, return 0. - /// lhs: an antisphere (solid outside, empty inside) - /// rhs: a sphere (empty outside, solid inside) - private static Vector3 GetOverlap_Antisphere_Sphere( - Vector3 lhsCenter, float lhsRadius, - Vector3 rhsCenter, float rhsRadius) - { - // If anyone passes negative values, they are a bad person - lhsRadius = Mathf.Abs(lhsRadius); - rhsRadius = Mathf.Abs(rhsRadius); - // Without loss of generality, can recenter on lhs - rhsCenter -= lhsCenter; - lhsCenter -= lhsCenter; - - float maxDistance = lhsRadius - rhsRadius; - - // Edge case: sphere does not fit in antisphere - if (maxDistance <= 0) - { - return -rhsCenter; - } - - float penetrationDistance = Mathf.Max(0, rhsCenter.magnitude - maxDistance); - return -penetrationDistance * rhsCenter.normalized; - } - - public static bool IsValidScenePose(TrTransform xf, float radialBounds) - { - // Simple and dumb implementation for now. - return xf == MakeValidScenePose(xf, radialBounds); - } - - /// This is like MakeValidScenePose, but it guarantees that: - /// - The return value is a valid result of Lerp(scene0, scene1, t), - /// for some handwavy definition of "lerp" - /// - The lerp "t" is in [0, 1] - /// - IsValidScenePose(return value) is true, subject to the previous constraints. - /// - /// Think of it as doing a cast from scene0 to scene1. - public static TrTransform MakeValidSceneMove( - TrTransform scene0, TrTransform scene1, float radialBounds) - { - if (IsValidScenePose(scene1, radialBounds)) - { - return scene1; - } - if (!IsValidScenePose(scene0, radialBounds)) - { - Debug.LogError("Invalid scene cast start"); - return scene0; - } - - // We don't support lerping either of these - Debug.Assert(scene0.rotation == scene1.rotation); - Debug.Assert(scene0.scale == scene1.scale); - - Vector3 vRoom0 = -scene0.translation; - Vector3 vRoom1 = -scene1.translation; - float radius = (scene0.scale - * radialBounds - * App.METERS_TO_UNITS) - App.Instance.RoomRadius; - - float t0, t1; - bool success = MathUtils.RaySphereIntersection( - vRoom0, vRoom1 - vRoom0, - Vector3.zero, radius, out t0, out t1); - if (!success) - { - // If this were more important, we could solve for the t of the closest approach - return scene0; - } - - // t0 is expected to be < 0 (room starts inside the fence) - // t1 is expected to be in [0, 1] (room ends outside the fence) - - // Constraints: - // - Lerp t must be in [0, 1]. (Do not move past the requested endpoint) - // - Lerp t should be as high as possible but < t1. (Do not exit the sphere) - float t = Mathf.Clamp(t1, 0, 1); - - TrTransform sceneT = TrTransform.TRS( - Vector3.Lerp(scene0.translation, scene1.translation, t), - scene0.rotation, - scene0.scale); - return MakeValidScenePose(sceneT, radialBounds); - } - - /// Returns a new ScenePose TrTransform that does not cause the room - /// to violate the hard scene bounds. - /// - /// scenePose - The current, possibly invalid scene pose - public static TrTransform MakeValidScenePose(TrTransform scenePose, float radialBounds) - { - scenePose.scale = Mathf.Clamp( - scenePose.scale, - SketchControlsScript.m_Instance.WorldTransformMinScale, - SketchControlsScript.m_Instance.WorldTransformMaxScale); - - // Anything not explicitly qualified is in room space. - - float roomRadius = App.Instance.RoomRadius; - Vector3 roomCenter = Vector3.zero; - - float fenceRadius = scenePose.scale * radialBounds - * App.METERS_TO_UNITS; - Vector3 fenceCenter = scenePose.translation; - - Vector3 moveRoom = GetOverlap_Antisphere_Sphere( - fenceCenter, fenceRadius, roomCenter, roomRadius); - Vector3 moveFence = -moveRoom; - - scenePose.translation += moveFence; - return scenePose; - } - - /// Clears data used by GetGrabWidgetHoldHistory() - /// Should be called any time m_GrabWidgetOneHandInfo changes - void ClearGrabWidgetHoldHistory() - { - m_GrabWidgetHoldHistory.Clear(); - } - - /// Collects data for use with GetGrabWidgetHoldHistory() - void UpdateGrabWidgetHoldHistory(InputManager.ControllerName name) - { - float t = Time.realtimeSinceStartup; - var info = InputManager.Controllers[(int)name]; - m_GrabWidgetHoldHistory.Enqueue(new GrabWidgetHoldPoint - { - m_Name = name, - m_BirthTime = t, - m_Pos = info.Transform.position, - m_Rot = info.Transform.rotation - }); - - // Trim the fat off our widget history - while (m_GrabWidgetHoldHistory.Count > 0 && - t - m_GrabWidgetHoldHistory.Peek().m_BirthTime >= kControlPointHistoryMaxTime) - { - m_GrabWidgetHoldHistory.Dequeue(); - } - } - - /// Returns possibly-smoothed linear and angular velocities. May fail. - /// Angular velocity is returned as an axial vector whose length() is degrees/second - bool GetGrabWidgetHoldHistory(out Vector3 vLinearVelocity, out Vector3 vAngularVelocity) - { - vLinearVelocity = vAngularVelocity = Vector3.zero; - if (m_GrabWidgetHoldHistory.Count < 2) - { - return false; - } - - // We need pairs of elements, so a simple foreach() won't quite work. - // Maybe using linq .First() and .Skip() would be okay. - using (IEnumerator enumerator = m_GrabWidgetHoldHistory.GetEnumerator()) - { - if (!enumerator.MoveNext()) - { - return false; - } - - // Infinitesimal rotations commute, and scaled-axis-angle rotations commute - // "better" than other rotation formats. - Vector3 totalDeltaTheta = Vector3.zero; - - GrabWidgetHoldPoint first = enumerator.Current; - GrabWidgetHoldPoint prev = first; - GrabWidgetHoldPoint current = first; - while (enumerator.MoveNext()) - { - current = enumerator.Current; - - // For our quaternion, find the difference, convert it to angle/axis, and sum it - // Find delta such that delta * prev = cur - // left-multiply because we want it in world-space. - // multiply vs prev since we want the delta that takes us forward in time - // rather than backward in time. - Quaternion dtheta = current.m_Rot * Quaternion.Inverse(prev.m_Rot); - // Assume the rotation took the shorter path - if (dtheta.w < 0) - { - dtheta.Set(-dtheta.x, -dtheta.y, -dtheta.z, -dtheta.w); - } - - float degrees; - Vector3 axis; - dtheta.ToAngleAxis(out degrees, out axis); - totalDeltaTheta += (axis * degrees); - prev = current; - } - - // Linear velocity calculation doesn't need to look at intermediate points - Vector3 totalDeltaPosition = current.m_Pos - first.m_Pos; - float totalDeltaTime = current.m_BirthTime - first.m_BirthTime; - if (totalDeltaTime == 0) - { - return false; - } - - vLinearVelocity = totalDeltaPosition / totalDeltaTime; - vAngularVelocity = totalDeltaTheta / totalDeltaTime; - return true; - } - } - - bool IsControllerNearWidget(InputManager.ControllerName name, GrabWidget widget) - { - Vector3 vControllerPos = InputManager.m_Instance.GetControllerAttachPointPosition(name); - return widget.GetActivationScore(vControllerPos, name) >= 0.0f; - } - - void RefreshCurrentGazeObject() - { - UnityEngine.Profiling.Profiler.BeginSample("SketchControlScript.RefreshCurrentGazeObject"); - int iPrevGazeObject = m_CurrentGazeObject; - m_CurrentGazeObject = -1; - bool bGazeAllowed = (m_CurrentInputState == InputState.Standard) - && !InputManager.m_Instance.GetCommand(InputManager.SketchCommands.Activate) - && !m_SketchSurfacePanel.ActiveTool.InputBlocked() - && (m_GrabWidgetState == GrabWidgetState.None) - && !m_GrabBrush.grabbingWorld - && !m_PinCushion.IsShowing() - && !PointerManager.MainPointerIsPainting() - ; - - bool bGazeDeactivationOverrideWithInput = false; - List aAllPanels = m_PanelManager.GetAllPanels(); - - bool hasController = m_ControlsType == ControlsType.SixDofControllers; - - //if we're re-positioning a panel, keep it active - if (m_PositioningPanelWithHead) - { - m_CurrentGazeObject = iPrevGazeObject; - } - // Only activate gaze objects if we're in standard input mode, and if we don't have the 'draw' - // button held. - else if ((bGazeAllowed || (iPrevGazeObject != -1))) - { - //reset hit flags - for (int i = 0; i < m_GazeResults.Length; ++i) - { - m_GazeResults[i].m_HitWithGaze = false; - m_GazeResults[i].m_HitWithController = false; - m_GazeResults[i].m_WithinView = false; - } - - // If we're in controller mode, find the nearest colliding widget that might get in our way. - float fNearestWidget = 99999.0f; - if (hasController) - { - fNearestWidget = m_WidgetManager.DistanceToNearestWidget(m_GazeControllerRay); - } - - //check all panels for gaze hit - bool bRequireVisibilityCheck = !hasController || (iPrevGazeObject == -1); - if (m_PanelManager.PanelsAreStable()) - { - RaycastHit rHitInfo; - bool bRayHit = false; - int panelsHit = 0; - for (int i = 0; i < aAllPanels.Count; ++i) - { - // Ignore fixed panels when they are not visible. - if (!m_PanelManager.GazePanelsAreVisible() && aAllPanels[i].m_Panel.m_Fixed) - { - continue; - } - - if (aAllPanels[i].m_Panel.gameObject.activeSelf && aAllPanels[i].m_Panel.IsAvailable()) - { - //make sure this b-snap is in view - Vector3 vToPanel = aAllPanels[i].m_Panel.transform.position - m_CurrentGazeRay.origin; - vToPanel.Normalize(); - if (!bRequireVisibilityCheck || Vector3.Angle(vToPanel, m_CurrentGazeRay.direction) < m_GazeMaxAngleFromFacing) - { - if (hasController) - { - if (aAllPanels[i].m_Panel.HasMeshCollider()) - { - //make sure the angle between the pointer and the panel forward is below our max angle - if (Vector3.Angle(aAllPanels[i].m_Panel.transform.forward, m_GazeControllerRay.direction) < m_GazeMaxAngleFromPointing) - { - //make sure the angle between the user-to-panel and the panel forward is reasonable - if (Vector3.Angle(aAllPanels[i].m_Panel.transform.forward, vToPanel) < m_GazeMaxAngleFacingToForward) - { - m_GazeResults[i].m_WithinView = true; - - bRayHit = false; - bRayHit = aAllPanels[i].m_Panel.RaycastAgainstMeshCollider( - m_GazeControllerRay, out rHitInfo, m_GazeControllerPointingDistance); - - if (bRayHit) - { - //if the ray starts inside the panel, we won't get a good hit point, it'll just be zero - if (rHitInfo.point.sqrMagnitude > 0.1f) - { - if (rHitInfo.distance < fNearestWidget) - { - m_GazeResults[i].m_ControllerDistance = rHitInfo.distance; - m_GazeResults[i].m_ControllerPosition = rHitInfo.point; - m_GazeResults[i].m_HitWithController = true; - panelsHit++; - } - } - } - } - } - } - } - else - { - m_GazeResults[i].m_WithinView = true; - if (aAllPanels[i].m_Panel.GetCollider().Raycast(m_CurrentGazeRay, out rHitInfo, m_GazeMaxDistance)) - { - m_GazeResults[i].m_GazePosition = rHitInfo.point; - m_GazeResults[i].m_HitWithGaze = true; - } - } - } - } - } - - // No panels hit within normal ray distance. - // Check if previous panel still pointed to. - if (panelsHit == 0) - { - if (iPrevGazeObject != -1) - { - // Don't allow any panel to hold focus if it's facing away from the user. - Vector3 vToPanel = aAllPanels[iPrevGazeObject].m_Panel.transform.position - - m_CurrentGazeRay.origin; - vToPanel.Normalize(); - if (Vector3.Angle(aAllPanels[iPrevGazeObject].m_Panel.transform.forward, vToPanel) < - m_GazeMaxAngleFacingToForward) - { - float fDist = m_GazeControllerPointingDistance * 1.5f; - bRayHit = aAllPanels[iPrevGazeObject].m_Panel.RaycastAgainstMeshCollider( - m_GazeControllerRayActivePanel, out rHitInfo, fDist); - if (bRayHit) - { - if (rHitInfo.point.sqrMagnitude > 0.1f) - { - if (rHitInfo.distance < fNearestWidget) - { - m_GazeResults[iPrevGazeObject].m_ControllerDistance = rHitInfo.distance; - m_GazeResults[iPrevGazeObject].m_ControllerPosition = rHitInfo.point; - m_GazeResults[iPrevGazeObject].m_HitWithController = true; - } - } - } - } - } - } - } - - //determine what panel we hit, take the one with the lowest controller distance - float fControllerDist = 999.0f; - int iControllerIndex = -1; - if (hasController) - { - for (int i = 0; i < m_GazeResults.Length; ++i) - { - if (m_GazeResults[i].m_HitWithController) - { - if (m_GazeResults[i].m_ControllerDistance < fControllerDist) - { - iControllerIndex = i; - fControllerDist = m_GazeResults[i].m_ControllerDistance; - } - } - } - } - - //if we found something near our controller, take it - if (iControllerIndex != -1) - { - m_CurrentGazeObject = iControllerIndex; - m_CurrentGazeHitPoint = m_GazeResults[iControllerIndex].m_ControllerPosition; - - // TODO: This should not be hardcoded once multiple pointers are allowed. - m_GazeResults[m_CurrentGazeObject].m_ControllerName = InputManager.ControllerName.Brush; - if (m_GazeResults[m_CurrentGazeObject].m_HitWithGaze) - { - //average with the gaze position if we hit that too - m_CurrentGazeHitPoint += m_GazeResults[m_CurrentGazeObject].m_GazePosition; - m_CurrentGazeHitPoint *= 0.5f; - } - } - else - { - //nothing near the controller, see if we're looking at the previous - if (iPrevGazeObject != -1 && m_GazeResults[iPrevGazeObject].m_HitWithGaze) - { - m_CurrentGazeObject = iPrevGazeObject; - m_CurrentGazeHitPoint = m_GazeResults[m_CurrentGazeObject].m_GazePosition; - } - else - { - //controller and gaze not near panel, pick the first panel we're looking at - for (int i = 0; i < m_GazeResults.Length; ++i) - { - if (m_GazeResults[i].m_HitWithGaze) - { - m_CurrentGazeObject = i; - m_CurrentGazeHitPoint = m_GazeResults[i].m_GazePosition; - break; - } - } - } - } - - //forcing users to look away from gaze panel - if (m_EatInputGazeObject && m_CurrentGazeObject != -1) - { - m_CurrentGazeObject = -1; - } - else if (m_CurrentGazeObject == -1) - { - m_EatInputGazeObject = false; - } - } - - //if we're staring at a panel, keep our countdown fresh - if (m_CurrentGazeObject != -1 || m_ForcePanelActivation) - { - m_GazePanelDectivationCountdown = m_GazePanelDectivationDelay; - } - else - { - if (InputManager.m_Instance.GetCommandDown(InputManager.SketchCommands.Activate)) - { - bGazeDeactivationOverrideWithInput = true; - m_GazePanelDectivationCountdown = 0.0f; - } - else - { - m_GazePanelDectivationCountdown -= Time.deltaTime; - } - if (m_GazePanelDectivationCountdown > 0.0f) - { - m_CurrentGazeObject = iPrevGazeObject; - } - } - - //update our positioning timer - if (m_PositioningPanelWithHead) - { - m_PositioningTimer += m_PositioningSpeed * Time.deltaTime; - m_PositioningTimer = Mathf.Min(m_PositioningTimer, 1.0f); - } - else - { - m_PositioningTimer -= m_PositioningSpeed * Time.deltaTime; - m_PositioningTimer = Mathf.Max(m_PositioningTimer, 0.0f); - } - - //prime objects if we change targets - if (iPrevGazeObject != m_CurrentGazeObject) - { - //if we're switching panels, make sure the pointer doesn't streak - PointerManager.m_Instance.DisablePointerPreviewLine(); - - if (iPrevGazeObject != -1) - { - aAllPanels[iPrevGazeObject].m_Panel.PanelGazeActive(false); - aAllPanels[iPrevGazeObject].m_Panel.SetPositioningPercent(0.0f); - } - if (m_CurrentGazeObject != -1) - { - //make sure our line is disabled - if (m_GazeResults[m_CurrentGazeObject].m_ControllerName == InputManager.ControllerName.Brush) - { - PointerManager.m_Instance.EnableLine(false); - PointerManager.m_Instance.AllowPointerPreviewLine(false); - } - - aAllPanels[m_CurrentGazeObject].m_Panel.PanelGazeActive(true); - aAllPanels[m_CurrentGazeObject].m_Panel.SetPositioningPercent(0.0f); - - if (m_GazeResults[m_CurrentGazeObject].m_ControllerName == InputManager.ControllerName.Brush) - { - m_SketchSurfacePanel.RequestHideActiveTool(true); - } - } - else - { - //if we don't have a panel, we need to enable the pointer according to the current tool - PointerManager.m_Instance.RefreshFreePaintPointerAngle(); - PointerManager.m_Instance.RequestPointerRendering(m_SketchSurfacePanel.ShouldShowPointer()); - m_UIReticle.SetActive(false); - m_SketchSurfacePanel.RequestHideActiveTool(false); - if (!bGazeDeactivationOverrideWithInput) - { - m_SketchSurfacePanel.EatToolsInput(); - } - } - - m_PositioningPanelWithHead = false; - } - UnityEngine.Profiling.Profiler.EndSample(); - } - - void UpdateActiveGazeObject() - { - BasePanel currentPanel = m_PanelManager.GetPanel(m_CurrentGazeObject); - currentPanel.SetPositioningPercent(m_PositioningTimer); - bool hasController = m_ControlsType == ControlsType.SixDofControllers; - // Update positioning behavior. - if (m_PositioningPanelWithHead) - { - if (!InputManager.m_Instance.GetCommand(InputManager.SketchCommands.LockToHead) && - !InputManager.m_Instance.GetCommand(InputManager.SketchCommands.LockToController)) - { - // No more positioning. - m_PositioningPanelWithHead = false; - m_PanelManager.m_SweetSpot.EnableBorderSphere(false, Vector3.zero, 0.0f); - currentPanel.PanelHasStoppedMoving(); - } - else - { - //lock the panel to the sweet spot bounds in the direction the user is looking - Quaternion qDiff = m_CurrentHeadOrientation * Quaternion.Inverse(m_PositioningPanelBaseHeadRotation); - Vector3 vAdjustedOffset = qDiff * m_PositioningPanelOffset; - - Vector3 vNewPos = m_PanelManager.m_SweetSpot.transform.position + vAdjustedOffset; - currentPanel.transform.position = vNewPos; - - vAdjustedOffset.Normalize(); - currentPanel.transform.forward = vAdjustedOffset; - - float fHighlightRadius = currentPanel.m_BorderSphereHighlightRadius; - m_PanelManager.m_SweetSpot.EnableBorderSphere(true, vNewPos, fHighlightRadius * m_PositioningTimer); - - //once we've moved this panel, run the simulation on the other panels to resolve collisions - m_PanelManager.DoCollisionSimulationForKeyboardMouse(currentPanel); - } - } - else - { - // It's possible that, on this frame, before this function was called, active gaze was pulled - // from this panel. In this case, we want to skip updating this frame. - // This happens when a panel has gaze and world grab dismisses all panels, for example. - if (currentPanel.IsActive()) - { - //orient to gaze - if (hasController) - { - currentPanel.UpdatePanel(m_GazeControllerRay.direction, m_CurrentGazeHitPoint); - } - else - { - currentPanel.UpdatePanel(m_CurrentGazeRay.direction, m_CurrentGazeHitPoint); - } - } - - if (!hasController) - { - //lock to head if we're holding a lock button.. - bool bLockToHead = InputManager.m_Instance.GetCommand(InputManager.SketchCommands.LockToHead) || - InputManager.m_Instance.GetCommand(InputManager.SketchCommands.LockToController); - - if (bLockToHead) - { - m_PositioningPanelWithHead = true; - m_PositioningPanelBaseHeadRotation = m_CurrentHeadOrientation; - m_PositioningPanelOffset = currentPanel.transform.position - - m_PanelManager.m_SweetSpot.transform.position; - - currentPanel.ResetPanelFlair(); - - //prime all other panels for movement - m_PanelManager.PrimeCollisionSimForKeyboardMouse(); - } - } - - PointerManager.m_Instance.RequestPointerRendering(false); - currentPanel.UpdateReticleOffset(m_MouseDeltaX, m_MouseDeltaY); - } - - // Keep reticle locked in the right spot. - Vector3 reticlePos = Vector3.zero; - Vector3 reticleForward = Vector3.zero; - if (hasController) - { - currentPanel.GetReticleTransformFromPosDir(m_CurrentGazeHitPoint, - m_GazeControllerRay.direction, out reticlePos, out reticleForward); - } - else - { - currentPanel.GetReticleTransform(out reticlePos, out reticleForward, - (m_ControlsType == ControlsType.ViewingOnly)); - } - - SetUIReticleTransform(reticlePos, -reticleForward); - m_UIReticle.SetActive(GetGazePanelActivationRatio() >= 1.0f); - } - - public void ResetActivePanel() - { - m_PanelManager.ResetPanel(m_CurrentGazeObject); - PointerManager.m_Instance.DisablePointerPreviewLine(); - m_PositioningPanelWithHead = false; - m_CurrentGazeObject = -1; - } - - void UpdatePanInput() - { - if (Mouse.current.rightButton.isPressed) - { - Vector3 vPanDiff = Vector3.zero; - vPanDiff += (Vector3.right * m_MouseDeltaXScaled); - vPanDiff += (Vector3.up * m_MouseDeltaYScaled); - Vector3 vSurfacePos = m_SketchSurface.transform.position; - m_SketchSurface.transform.position = vSurfacePos + vPanDiff; - } - else - { - float fCurrentTime = Time.realtimeSinceStartup; - if (fCurrentTime - m_PositionOffsetResetTapTime < m_DoubleTapWindow) - { - if (m_CurrentGazeObject == -1) - { - ResetGrabbedPose(); - } - } - m_PositionOffsetResetTapTime = fCurrentTime; - - SwitchState(InputState.Standard); - } - } - - void UpdateRotationInput() - { - if (InputManager.m_Instance.GetCommand(InputManager.SketchCommands.PivotRotation)) - { - bool bAltInputActive = InputManager.m_Instance.GetCommand(InputManager.SketchCommands.AltActivate); - bool bRollRotation = m_RotationRollActive || bAltInputActive || m_CurrentRotationType == RotationType.RollOnly; - m_RotationIcon.SetActive(bRollRotation); - if (bRollRotation) - { - m_RotationCursorOffset.x += m_MouseDeltaXScaled; - float fRotationAmount = m_RotationCursorOffset.x * -m_RotationRollScalar; - - Quaternion qOffsetRotation = Quaternion.AngleAxis(fRotationAmount, m_SurfaceForward); - Quaternion qNewRotation = qOffsetRotation * m_RotationOrigin; - m_SketchSurface.transform.rotation = qNewRotation; - - m_RotationRollActive = true; - m_RotationCursor.gameObject.SetActive(false); - } - else - { - //update offset with mouse movement - m_RotationCursorOffset.x += m_MouseDeltaXScaled; - m_RotationCursorOffset.y += m_MouseDeltaYScaled; - - //get offset in model space - Vector3 vSurfaceBounds = m_SketchSurface.transform.localScale * 0.5f; - m_RotationCursorOffset.x = Mathf.Clamp(m_RotationCursorOffset.x, -vSurfaceBounds.x, vSurfaceBounds.x); - m_RotationCursorOffset.y = Mathf.Clamp(m_RotationCursorOffset.y, -vSurfaceBounds.y, vSurfaceBounds.y); - float fCursorOffsetDist = m_RotationCursorOffset.magnitude; - float fMaxCursorOffsetDist = vSurfaceBounds.x; - - //transform offset in to world space - Vector3 vTransformedOffset = m_RotationOrigin * m_RotationCursorOffset; - vTransformedOffset.Normalize(); - - //get world space rotation axis - Vector3 vSketchSurfaceRotationAxis = Vector3.Cross(vTransformedOffset, m_SurfaceForward); - vSketchSurfaceRotationAxis.Normalize(); - - //amount to rotate is determined by offset distance from origin - float fSketchSurfaceRotationAngle = Mathf.Min(fCursorOffsetDist / fMaxCursorOffsetDist, 1.0f); - fSketchSurfaceRotationAngle *= m_RotationMaxAngle; - - //set new surface rotation by combining base rotation with angle/axis rotation - Quaternion qOffsetRotation = Quaternion.AngleAxis(fSketchSurfaceRotationAngle, vSketchSurfaceRotationAxis); - Quaternion qNewRotation = qOffsetRotation * m_RotationOrigin; - m_SketchSurface.transform.rotation = qNewRotation; - - //set position of rotation cursor - Vector3 vNewTransformedOffset = qNewRotation * m_RotationCursorOffset; - m_RotationCursor.transform.position = m_SketchSurface.transform.position + vNewTransformedOffset; - m_RotationCursor.transform.rotation = qNewRotation; - - //set position of guide lines - Vector2 vToCenter = m_RotationCursorOffset; - vToCenter.Normalize(); - float fOffsetAngle = Vector2.Angle(vToCenter, Vector2.up); - m_RotationCursor.PositionCursorLines(m_SketchSurface.transform.position, m_SketchSurface.transform.forward, fOffsetAngle, vSurfaceBounds.x * 2.0f); - } - } - else - { - float fCurrentTime = Time.realtimeSinceStartup; - if (fCurrentTime - m_RotationResetTapTime < m_DoubleTapWindow) - { - //reset drawing surface rotation - m_SketchSurface.transform.rotation = Quaternion.identity; - } - m_RotationResetTapTime = fCurrentTime; - - m_SurfaceForward = m_SketchSurface.transform.forward; - m_SurfaceRight = m_SketchSurface.transform.right; - m_SurfaceUp = m_SketchSurface.transform.up; - - if (!m_RotationRollActive && m_AutoOrientAfterRotation && m_SketchSurfacePanel.IsSketchSurfaceToolActive()) - { - //get possible auto rotations - Quaternion qQuatUp = OrientSketchSurfaceToUp(); - Quaternion qQuatForward = OrientSketchSurfaceToForward(); - - //get the angle between our current and desired auto-rotation - float toUpAngle = Quaternion.Angle(qQuatUp, m_SketchSurface.transform.rotation); - float toForwardAngle = Quaternion.Angle(qQuatForward, m_SketchSurface.transform.rotation); - - //set our new rotation to be whichever autorotation is closeset - Quaternion qNewRotation; - if (Mathf.Abs(toUpAngle) < Mathf.Abs(toForwardAngle)) - { - qNewRotation = qQuatUp; - } - else - { - qNewRotation = qQuatForward; - } - - //update the sketch surface - m_SketchSurface.transform.rotation = qNewRotation; - - m_SurfaceForward = m_SketchSurface.transform.forward; - m_SurfaceRight = m_SketchSurface.transform.right; - m_SurfaceUp = m_SketchSurface.transform.up; - } - - SwitchState(InputState.Standard); - } - } - - void UpdateHeadLockInput() - { - if (InputManager.m_Instance.GetCommand(InputManager.SketchCommands.LockToHead)) - { - //compute new position/orientation of sketch surface - Vector3 vTransformedOffset = m_CurrentHeadOrientation * m_SurfaceLockOffset; - Vector3 vSurfacePos = m_CurrentGazeRay.origin + vTransformedOffset; - - Quaternion qDiff = m_CurrentHeadOrientation * Quaternion.Inverse(m_SurfaceLockBaseHeadRotation); - Quaternion qNewSurfaceRot = qDiff * m_SurfaceLockBaseSurfaceRotation; - - m_SketchSurface.transform.position = vSurfacePos; - m_SketchSurface.transform.rotation = qNewSurfaceRot; - } - else - { - m_SurfaceForward = m_SketchSurface.transform.forward; - m_SurfaceRight = m_SketchSurface.transform.right; - m_SurfaceUp = m_SketchSurface.transform.up; - - SwitchState(InputState.Standard); - } - } - - void UpdateControllerLock() - { - if (InputManager.m_Instance.GetCommand(InputManager.SketchCommands.LockToController)) - { - //compute new position/orientation of sketch surface - Vector3 vControllerDiff = InputManager.m_Instance.GetControllerPosition(m_SurfaceLockActingController) - m_SurfaceLockBaseControllerPosition; - m_SketchSurface.transform.position = m_SurfaceLockBaseSurfacePosition + (vControllerDiff * m_SurfaceLockControllerScalar); - - Quaternion qDiff = InputManager.m_Instance.GetControllerRotation(m_SurfaceLockActingController) * Quaternion.Inverse(m_SurfaceLockBaseControllerRotation); - m_SketchSurface.transform.rotation = qDiff * m_SurfaceLockBaseSurfaceRotation; - } - else - { - m_SurfaceForward = m_SketchSurface.transform.forward; - m_SurfaceRight = m_SketchSurface.transform.right; - m_SurfaceUp = m_SketchSurface.transform.up; - - SwitchState(InputState.Standard); - } - } - - void UpdatePushPullInput() - { - bool bRotationActive = InputManager.m_Instance.GetCommand(InputManager.SketchCommands.PivotRotation); - bool bInputActive = InputManager.m_Instance.GetCommand(InputManager.SketchCommands.Activate); - bool bAltInputActive = InputManager.m_Instance.GetCommand(InputManager.SketchCommands.AltActivate); - - if (bRotationActive && bInputActive) - { - SwitchState(InputState.Rotation); - } - else if (bAltInputActive) - { - Vector3 vPos = m_SketchSurface.transform.position; - float fBigDiff = Mathf.Abs(m_MouseDeltaXScaled) > Mathf.Abs(m_MouseDeltaYScaled) ? -m_MouseDeltaXScaled : m_MouseDeltaYScaled; - vPos += Vector3.forward * fBigDiff; - - m_SketchSurface.transform.position = vPos; - } - else - { - SwitchState(InputState.Standard); - } - } - - void UpdateSaveInput() - { - if (!InputManager.m_Instance.GetKeyboardShortcut(InputManager.KeyboardShortcut.Save)) - { - SwitchState(InputState.Standard); - } - } - - void UpdateLoadInput() - { - if (!InputManager.m_Instance.GetKeyboardShortcut(InputManager.KeyboardShortcut.Load)) - { - SwitchState(InputState.Standard); - } - } - - void OnBrushSetToDefault() - { - BrushDescriptor rDefaultBrush = BrushCatalog.m_Instance.DefaultBrush; - PointerManager.m_Instance.SetBrushForAllPointers(rDefaultBrush); - PointerManager.m_Instance.SetAllPointersBrushSize01(0.5f); - PointerManager.m_Instance.MarkAllBrushSizeUsed(); - } - - public void AssignControllerMaterials(InputManager.ControllerName controller) - { - ControllerGeometry geometry = InputManager.GetControllerGeometry(controller); - - // Start from a clean state - geometry.ResetAll(); - - // If the tutorial is enabled, override all materials. - if (TutorialManager.m_Instance.TutorialActive()) - { - InputManager.m_Instance - .GetControllerTutorial(controller) - ?.AssignControllerMaterials(controller); - return; - } - - // If we're grabbing the world, get the materials from the world transform panel. - if (m_GrabBrush.grabbingWorld && controller == InputManager.ControllerName.Brush) - { - TrTransform scenePose = App.Scene.Pose; - if (scenePose.scale != 1 || scenePose.translation != Vector3.zero - || scenePose.rotation != Quaternion.identity) - { - geometry.ShowWorldTransformReset(); - } - return; - } - else if (m_GrabWand.grabbingWorld && controller == InputManager.ControllerName.Wand) - { - TrTransform scenePose = App.Scene.Pose; - if (scenePose.scale != 1 || scenePose.translation != Vector3.zero - || scenePose.rotation != Quaternion.identity) - { - geometry.ShowWorldTransformReset(); - } - return; - } - - // Not grabbing the world, so see if we're grabbing a widget. - if (m_GrabWidgetState != GrabWidgetState.None) - { - m_CurrentGrabWidget.AssignControllerMaterials(controller); - return; - } - - // See if we're highlighting a widget and if that matters. - if (m_CurrentGrabWidget != null && m_CurrentGrabWidget.HasHoverInteractions()) - { - m_CurrentGrabWidget.AssignHoverControllerMaterials(controller); - return; - } - - // Not grabbing the world or a widget, see if we're interacting with a panel. - if (controller == InputManager.ControllerName.Brush && m_CurrentGazeObject != -1) - { - BasePanel panel = m_PanelManager.GetPanel(m_CurrentGazeObject); - panel.AssignControllerMaterials(controller); - return; - } - - // Defaults. - if (controller == InputManager.ControllerName.Wand) - { - if (App.CurrentState != App.AppState.Standard || m_PanelManager.IntroSketchbookMode) - { - // If app is not in standard mode, the actions represented by subsequent material - // assigments cannot be taken. - return; - } - bool creatingStroke = PointerManager.m_Instance.IsMainPointerCreatingStroke(); - bool allowPainting = App.Instance.IsInStateThatAllowsPainting(); - - InputManager.Wand.Geometry.ShowRotatePanels(); - InputManager.Wand.Geometry.ShowUndoRedo(CanUndo() && !creatingStroke && allowPainting, - CanRedo() && !creatingStroke && allowPainting); - } - - // Show the pin cushion icon on the button if it's available. - if (controller == InputManager.ControllerName.Brush && CanUsePinCushion()) - { - InputManager.Brush.Geometry.ShowPinCushion(); - } - - // Finally, override with tools. - m_SketchSurfacePanel.AssignControllerMaterials(controller); - } - - public float GetControllerPadShaderRatio( - InputManager.ControllerName controller, VrInput input) - { - // If we're interacting with a panel, get touch ratio from the panel. - if (controller == InputManager.ControllerName.Brush && m_CurrentGazeObject != -1) - { - BasePanel panel = m_PanelManager.GetPanel(m_CurrentGazeObject); - return panel.GetControllerPadShaderRatio(controller); - } - return SketchSurfacePanel.m_Instance.GetCurrentToolSizeRatio(controller, input); - } - - void SwitchState(InputState rDesiredState) - { - //exit current state - switch (m_CurrentInputState) - { - case InputState.Pan: - m_TransformGizmoScript.ResetTransform(); - break; - case InputState.PushPull: - m_TransformGizmoScript.ResetTransform(); - break; - case InputState.Rotation: - m_RotationRollActive = false; - m_RotationIcon.SetActive(false); - m_RotationCursor.gameObject.SetActive(false); - break; - } - - bool bSketchSurfaceToolActive = m_SketchSurfacePanel.IsSketchSurfaceToolActive(); - - //enter new state - switch (rDesiredState) - { - case InputState.Pan: - m_TransformGizmoScript.SetTransformForPan(); - break; - case InputState.PushPull: - m_TransformGizmoScript.SetTransformForPushPull(); - break; - case InputState.Rotation: - if (bSketchSurfaceToolActive) - { - m_SketchSurface.transform.position = PointerManager.m_Instance.MainPointer.transform.position; - m_SketchSurfacePanel.ResetReticleOffset(); - } - m_RotationOrigin = m_SketchSurface.transform.rotation; - m_RotationCursorOffset = Vector2.zero; - m_RotationCursor.transform.position = m_SketchSurface.transform.position; - m_RotationCursor.transform.rotation = m_SketchSurface.transform.rotation; - m_RotationCursor.ClearCursorLines(m_SketchSurface.transform.position); - m_RotationCursor.gameObject.SetActive(bSketchSurfaceToolActive); - break; - case InputState.HeadLock: - m_SurfaceLockBaseHeadRotation = m_CurrentHeadOrientation; - m_SurfaceLockBaseSurfaceRotation = m_SketchSurface.transform.rotation; - m_SurfaceLockOffset = m_SketchSurface.transform.position - m_CurrentGazeRay.origin; - m_SurfaceLockOffset = Quaternion.Inverse(m_SurfaceLockBaseHeadRotation) * m_SurfaceLockOffset; - break; - case InputState.ControllerLock: - if (bSketchSurfaceToolActive) - { - m_SketchSurface.transform.position = PointerManager.m_Instance.MainPointer.transform.position; - m_SketchSurfacePanel.ResetReticleOffset(); - } - m_SurfaceLockActingController = InputManager.m_Instance.GetDominantController(InputManager.SketchCommands.LockToController); - m_SurfaceLockBaseSurfaceRotation = m_SketchSurface.transform.rotation; - m_SurfaceLockBaseControllerRotation = InputManager.m_Instance.GetControllerRotation(m_SurfaceLockActingController); - m_SurfaceLockBaseSurfacePosition = m_SketchSurface.transform.position; - m_SurfaceLockBaseControllerPosition = InputManager.m_Instance.GetControllerPosition(m_SurfaceLockActingController); - m_SurfaceLockControllerScalar = m_SketchSurfacePanel.m_PanelSensitivity / m_SurfaceLockControllerBaseScalar; - break; - case InputState.Save: - IssueGlobalCommand(GlobalCommands.Save); - break; - case InputState.Load: - IssueGlobalCommand(GlobalCommands.Load); - break; - } - - m_CurrentInputState = rDesiredState; - } - - public void RequestPanelsVisibility(bool bVisible) - { - // Always false in viewonly mode - bVisible = m_ViewOnly ? false : bVisible; - m_PanelsVisibilityRequested = bVisible; - } - - Quaternion OrientSketchSurfaceToUp() - { - //project the world up vector on to the surface plane - Vector3 vUpOnSurfacePlane = Vector3.up - (Vector3.Dot(Vector3.up, m_SurfaceForward) * m_SurfaceForward); - vUpOnSurfacePlane.Normalize(); - - //get the angle between the surface up and the projected world up - float fUpOnSurfacePlaneAngle = Vector3.Angle(vUpOnSurfacePlane, m_SurfaceUp); - Vector3 vUpCross = Vector3.Cross(vUpOnSurfacePlane, m_SurfaceUp); - vUpCross.Normalize(); - if (Vector3.Dot(vUpCross, m_SurfaceForward) > 0.0f) - { - fUpOnSurfacePlaneAngle *= -1.0f; - } - - //rotate around the surface foward by the angle diff - Quaternion qOrientToUp = Quaternion.AngleAxis(fUpOnSurfacePlaneAngle, m_SurfaceForward); - Quaternion qNewRotation = qOrientToUp * m_SketchSurface.transform.rotation; - return qNewRotation; - } - - Quaternion OrientSketchSurfaceToForward() - { - //project the world forward vector on to the surface plane - Vector3 vForwardOnSurfacePlane = Vector3.forward - (Vector3.Dot(Vector3.forward, m_SurfaceForward) * m_SurfaceForward); - vForwardOnSurfacePlane.Normalize(); - - //get the angle between the surface up and the projected world forward - float fForwardOnSurfacePlaneAngle = Vector3.Angle(vForwardOnSurfacePlane, m_SurfaceUp); - Vector3 vUpCross = Vector3.Cross(vForwardOnSurfacePlane, m_SurfaceUp); - vUpCross.Normalize(); - if (Vector3.Dot(vUpCross, m_SurfaceForward) > 0.0f) - { - fForwardOnSurfacePlaneAngle *= -1.0f; - } - - //rotate around the surface foward by the angle diff - Quaternion qOrientToForward = Quaternion.AngleAxis(fForwardOnSurfacePlaneAngle, m_SurfaceForward); - Quaternion qNewRotation = qOrientToForward * m_SketchSurface.transform.rotation; - return qNewRotation; - } - - /// Reset the scene or the canvas, depending on the current mode - public void ResetGrabbedPose(bool everything = false) - { - //update sketch surface position with offset to sweet spot - m_SketchSurface.transform.position = m_PanelManager.GetSketchSurfaceResetPos(); - if (everything) - { - App.Scene.Pose = TrTransform.identity; - Coords.CanvasLocalPose = TrTransform.identity; - } - App.Scene.Pose = TrTransform.identity; - - //reset orientation and pointer - ResetSketchSurfaceOrientation(); - m_SketchSurfacePanel.ResetReticleOffset(); - PointerManager.m_Instance.DisablePointerPreviewLine(); - PointerManager.m_Instance.SetPointerPreviewLineDelayTimer(); - } - - public void ResetSketchSurfaceOrientation() - { - m_SketchSurface.transform.rotation = Quaternion.identity; - m_SurfaceForward = m_SketchSurface.transform.forward; - m_SurfaceRight = m_SketchSurface.transform.right; - m_SurfaceUp = m_SketchSurface.transform.up; - } - - float GetAppropriateMovementScalar() - { - switch (m_CurrentInputState) - { - case InputState.Pan: return m_PanScalar; - case InputState.Rotation: return m_RotationScalar; - case InputState.PushPull: return m_PushPullScale; - } - - return 1.0f; - } - - // TODO - it'd be great if we could disentangle this from the multicam. - IEnumerator RenderPathAndQuit() - { -#if USD_SUPPORTED - App.Instance.SetDesiredState(App.AppState.OfflineRendering); - SketchSurfacePanel.m_Instance.EnableSpecificTool(BaseTool.ToolType.MultiCamTool); - MultiCamTool multiCam = SketchSurfacePanel.m_Instance.ActiveTool as MultiCamTool; - Debug.Assert(multiCam != null); // Something's gone wrong if we've been unable to find multicam! - if (multiCam == null) - { - yield break; - } - multiCam.ExternalObjectForceCameraStyle(MultiCamStyle.Video); - MultiCamCaptureRig.ForceClippingPlanes(MultiCamStyle.Video); - // Give the video tool time to switch - TODO - be a little more graceful here - yield return new WaitForSeconds(2); - // Make sure the videos have had time to load, and set playing ones to start - while (VideoCatalog.Instance.IsScanning) - { - yield return null; - } - foreach (var widget in WidgetManager.m_Instance.VideoWidgets) - { - if (widget.VideoController.Playing) - { - widget.VideoController.Position = 0; - } - } - yield return null; - var ssMgr = MultiCamCaptureRig.ManagerFromStyle(MultiCamStyle.Video); - ssMgr.SetScreenshotResolution(App.UserConfig.Video.OfflineResolution); - multiCam.StartVideoCapture(MultiCamTool.GetSaveName(MultiCamStyle.Video), offlineRender: true); - App.Instance.FrameCountDisplay.gameObject.SetActive(true); - App.Instance.FrameCountDisplay.SetFramesTotal(VideoRecorderUtils.NumFramesInUsdSerializer); - while (VideoRecorderUtils.ActiveVideoRecording != null) - { - App.Instance.FrameCountDisplay.SetCurrentFrame( - VideoRecorderUtils.ActiveVideoRecording.FrameCount); - yield return null; - } - ssMgr.SetScreenshotResolution(App.UserConfig.Video.Resolution); -#else - Debug.LogError("Render path requires USD support"); - yield return null; -#endif - QuitApp(); - } - - IEnumerator ExportListAndQuit() - { - App.Config.m_ForceDeterministicBirthTimeForExport = true; - List filesToExport = new List(); - foreach (string filePattern in App.Config.m_FilePatternsToExport) - { - bool absolute = Path.IsPathRooted(filePattern); - string directory = absolute ? Path.GetDirectoryName(filePattern) : App.UserSketchPath(); - string filename = Path.GetFileName(filePattern); - var tiltFiles = Directory.GetFiles(directory, filename); - filesToExport.AddRange(tiltFiles); - // Also look at .tilt files which have been unzipped into directory format - var tiltDirs = Directory.GetDirectories(directory, filename) - .Where(n => n.EndsWith(".tilt")); - filesToExport.AddRange(tiltDirs); - } - - using (var coroutine = LoadAndExportList(filesToExport)) - { - while (coroutine.MoveNext()) - { - yield return coroutine.Current; - } - } - QuitApp(); - } - - void QuitApp() - { - // We're done! Quit! -#if UNITY_EDITOR - UnityEditor.EditorApplication.isPlaying = false; -#else - Application.Quit(); -#endif - } - - // This coroutine must be run to completion or disposed. - IEnumerator LoadAndExportList(List filenames) - { - foreach (var filename in filenames) - { - using (var coroutine = LoadAndExport(filename)) - { - while (coroutine.MoveNext()) - { - yield return coroutine.Current; - } - } - } - } - - // This coroutine must be run to completion or disposed. - IEnumerator LoadAndExportAll() - { - SketchSet sketchSet = SketchCatalog.m_Instance.GetSet(SketchSetType.User); - for (int i = 0; i < SketchCatalog.m_Instance.GetSet(SketchSetType.User).NumSketches; ++i) - { - SceneFileInfo rInfo = sketchSet.GetSketchSceneFileInfo(i); - using (var coroutine = LoadAndExport(rInfo.FullPath)) - { - while (coroutine.MoveNext()) - { - yield return coroutine.Current; - } - } - } - } - - /// Loads a .tilt file completely. - /// This may be slightly buggy; it's not currently used for production. - /// This coroutine must be run to completion or disposed. - public IEnumerable LoadTiltFile(string filename) - { - using (var unused = new SceneSettings.RequestInstantSceneSwitch()) - { - IssueGlobalCommand( - GlobalCommands.LoadNamedFile, - iParam1: (int)LoadSpeed.Quick, sParam: filename); - yield return null; - while (App.Instance.IsLoading()) - { - yield return null; - } - - // I don't know why App.Instance.IsLoading() doesn't cover this, but it doesn't. - while (m_WidgetManager.CreatingMediaWidgets) - { - yield return null; - } - while (WidgetManager.m_Instance.AreMediaWidgetsStillLoading()) - { - yield return null; - } - - // This is kind of a hack. - // Despite the RequestInstantSceneSwitch above, I think scene colors still require - // a few frames to settle; also, GrabWidgets need to register themselves on the - // first frame, etc. - for (int i = 0; i < 10; ++i) - { - yield return null; - } - } - } - - // This coroutine must be run to completion or disposed. - IEnumerator LoadAndExport(string filename) - { - foreach (var val in LoadTiltFile(filename)) - { - yield return val; - } - using (var coroutine = ExportCoroutine()) - { - while (coroutine.MoveNext()) - { - yield return coroutine.Current; - } - } - } - - IEnumerator ExportCoroutine() - { - return OverlayManager.m_Instance.RunInCompositor( - OverlayType.Export, () => - { - // Sort of a kludge: put stuff back into the main canvas - SelectionManager.m_Instance.ClearActiveSelection(); - Export.ExportScene(); - }, 0.25f, false, true); - } - - private void SaveModel() - { -#if USD_SUPPORTED - var current = SaveLoadScript.m_Instance.SceneFile; - string basename = (current.Valid) - ? Path.GetFileNameWithoutExtension(current.FullPath) - : "Untitled"; - string directoryName = FileUtils.GenerateNonexistentFilename( - App.ModelLibraryPath(), basename, ""); - - string usdname = Path.Combine(directoryName, basename + ".usd"); - // TODO: export selection only, though this is still only experimental. The blocking - // issue to implement this is that the export collector needs to expose this as an option. - // - // SelectionManager.m_Instance.HasSelection - // ? SelectionManager.m_Instance.SelectedStrokes - // : null - ExportUsd.ExportPayload(usdname); - OutputWindowScript.m_Instance.CreateInfoCardAtController( - InputManager.ControllerName.Brush, "Model created!"); -#endif - } - - /// Generates a view from the previous thumbnail viewpoint. - public void GenerateReplacementSaveIcon() - { - if (SaveLoadScript.m_Instance.LastThumbnail_SS.HasValue) - { - TrTransform thumbnailInGlobalSpace = App.Scene.Pose * - SaveLoadScript.m_Instance.LastThumbnail_SS.Value; - - m_SaveIconTool.ProgrammaticCaptureSaveIcon(thumbnailInGlobalSpace.translation, - thumbnailInGlobalSpace.rotation); - } - else - { - GenerateBestGuessSaveIcon(); - } - } - - public void GenerateBestGuessSaveIcon() - { - TrTransform camXform = GenerateBestGuessSaveIconTransform(); - m_SaveIconTool.ProgrammaticCaptureSaveIcon(camXform.translation, camXform.rotation); - } - - /// This positions the save icon camera at the user's head position, and faces it towards - /// the most recent strokes the user has created. - /// If there are no strokes, it faces towards the 'most recent' models. - /// Sadly we cannot really mix the two as we don't know when the models were instantiated. - public TrTransform GenerateBestGuessSaveIconTransform(int itemsToEnumerate = 0) - { - if (itemsToEnumerate == 0) - { - itemsToEnumerate = m_NumStrokesForSaveIcon; - } - int startIndex = Mathf.Max(0, SketchMemoryScript.AllStrokesCount() - itemsToEnumerate); - var lastFewStrokes = SketchMemoryScript.AllStrokes().Skip(startIndex).ToArray(); - - Bounds bounds; - if (lastFewStrokes.Length > 0) - { - bounds = new Bounds(lastFewStrokes.First().m_ControlPoints.First().m_Pos, Vector3.zero); - foreach (var stroke in lastFewStrokes.Skip(1)) - { - bounds.Encapsulate(stroke.m_ControlPoints.First().m_Pos); - bounds.Encapsulate(stroke.m_ControlPoints.Last().m_Pos); - } - } - else - { - // If we have no strokes, just use the aggregates bounding boxes of the blocks models. - var models = m_WidgetManager.ModelWidgets.ToArray(); - // we should always have models to get here, but just in case... - if (models.Length > 0) - { - startIndex = Mathf.Max(0, models.Length - itemsToEnumerate); - bounds = models[startIndex].WorldSpaceBounds; - for (int i = startIndex + 1; i < models.Length; ++i) - { - bounds.Encapsulate(models[i].WorldSpaceBounds); - } - } - else - { - bounds = new Bounds(new Vector3(0, 1, -100000), Vector3.one); // some point in the distance - } - } - - Vector3 camPos = ViewpointScript.Head.position; - Vector3 worldPos = App.Scene.Pose.MultiplyPoint(bounds.center); - Quaternion direction = Quaternion.LookRotation(worldPos - camPos); - return TrTransform.TR(camPos, direction); - } - - - public void GenerateBoundingBoxSaveIcon() - { - Vector3 vNewCamPos; - { - Bounds rCanvasBounds = App.Scene.AllCanvases - .Select(canvas => canvas.GetCanvasBoundingBox()) - .Aggregate((b1, b2) => - { - b1.Encapsulate(b2); - return b1; - }); - - //position the camera at the center of the canvas bounds - vNewCamPos = rCanvasBounds.center; - - //back the camera up, along -z until we can see the extent of the bounds - float fCanvasWidth = rCanvasBounds.max.x - rCanvasBounds.min.x; - float fCanvasHeight = rCanvasBounds.max.y - rCanvasBounds.min.y; - float fLargerExtent = Mathf.Max(fCanvasHeight, fCanvasWidth); - - //half fov for camera - float fHalfFOV = m_SaveIconTool.ScreenshotManager.LeftEye.fieldOfView * 0.5f; - - //TODO: find the real reason this isn't working as it should - float fMagicNumber = 1.375f; - - //set new cam position and zero out orientation - float fBackupDistance = (fLargerExtent * 0.5f) - * Mathf.Tan(Mathf.Deg2Rad * fHalfFOV) * fMagicNumber; - vNewCamPos.z = rCanvasBounds.min.z - fBackupDistance; - } - - m_SaveIconTool.ProgrammaticCaptureSaveIcon(vNewCamPos, Quaternion.identity); - } - - private void MergeBrushStrokes(SceneFileInfo fileInfo) - { - m_PanelManager.ToggleSketchbookPanels(isLoadingSketch: true); - PointerManager.m_Instance.EnablePointerStrokeGeneration(true); - if (SaveLoadScript.m_Instance.Load(fileInfo, true)) - { - SketchMemoryScript.m_Instance.SetPlaybackMode(m_SketchPlaybackMode, m_DefaultSketchLoadSpeed); - SketchMemoryScript.m_Instance.BeginDrawingFromMemory(bDrawFromStart: true, false, false); - // the order of these two lines are important as ExitIntroSketch is setting the - // color of the pointer and we need the color to be set before we go to the Loading - // state. App script's ShouldTintControllers allow the controller to be tinted only - // when the app is in the standard mode. That was there to prevent the controller color - // from flickering while in the intro mode. - App.Instance.ExitIntroSketch(); - App.Instance.SetDesiredState(App.AppState.QuickLoad); - } - } - - public void LoadSketch(SceneFileInfo fileInfo, bool quickload = false, bool additive = false) - { - LightsControlScript.m_Instance.DiscoMode = false; - m_WidgetManager.FollowingPath = false; - m_WidgetManager.CameraPathsVisible = false; - m_WidgetManager.DestroyAllWidgets(); - m_PanelManager.ToggleSketchbookPanels(isLoadingSketch: true); - ResetGrabbedPose(everything: true); - PointerManager.m_Instance.EnablePointerStrokeGeneration(true); - if (SaveLoadScript.m_Instance.Load(fileInfo, additive)) - { - SketchMemoryScript.m_Instance.SetPlaybackMode(m_SketchPlaybackMode, m_DefaultSketchLoadSpeed); - SketchMemoryScript.m_Instance.BeginDrawingFromMemory(bDrawFromStart: true); - // the order of these two lines are important as ExitIntroSketch is setting the - // color of the pointer and we need the color to be set before we go to the Loading - // state. App script's ShouldTintControllers allow the controller to be tinted only - // when the app is in the standard mode. That was there to prevent the controller color - // from flickering while in the intro mode. - App.Instance.ExitIntroSketch(); - App.Instance.SetDesiredState(quickload ? App.AppState.QuickLoad : App.AppState.Loading); - } - QualityControls.m_Instance.ResetAutoQuality(); - m_WidgetManager.ValidateCurrentCameraPath(); - } - - public void IssueGlobalCommand(GlobalCommands rEnum, int iParam1 = -1, - int iParam2 = -1, string sParam = null) - { - switch (rEnum) - { - - // Keyboard command, for debugging and emergency use. - case GlobalCommands.Save: - { - if (!FileUtils.CheckDiskSpaceWithError(App.UserSketchPath())) - { - return; - } - // Disable active selection before saving. - // This looks fishy, here's what's going on: When an object is selected and it has moved, the - // the user is observing the selection canvas in the HMD, but we will be saving the main canvas. - // Because they haven't deselected yet, the selection canvas and the main canvas are out of sync - // so the strokes that will be saved will not match what the user sees. - // - // Here we deselect to force the main canvas to sync with the selection canvas, which is more - // correct from the user's perspective. Push the deselect operation onto the stack so the user - // can undo it after save, if desired. - SelectionManager.m_Instance.ClearActiveSelection(); - GenerateReplacementSaveIcon(); - if (iParam1 == -1) - { - if (iParam2 == 1) - { - // Do a save in Tiltasaurus mode, which creates a new filename prefixed with - // "Tiltasaurus_" and the current prompt. Also, don't eat gaze input so that the - // Tiltasaurus prompt stays open. - StartCoroutine(SaveLoadScript.m_Instance.SaveOverwrite(tiltasaurusMode: true)); - } - else - { - StartCoroutine(SaveLoadScript.m_Instance.SaveOverwrite()); - EatGazeObjectInput(); - } - } - else - { - StartCoroutine(SaveLoadScript.m_Instance.SaveMonoscopic(iParam1)); - } - break; - } - case GlobalCommands.SaveNew: - { - if (!FileUtils.CheckDiskSpaceWithError(App.UserSketchPath())) - { - return; - } - if (iParam1 == 1) - { - GenerateBoundingBoxSaveIcon(); - } - StartCoroutine(SaveLoadScript.m_Instance.SaveNewName()); - EatGazeObjectInput(); - break; - } - case GlobalCommands.SaveAndUpload: - { - if (!FileUtils.CheckDiskSpaceWithError(App.UserSketchPath())) - { - Debug.LogError("SaveAndUpload: Disk space error"); - return; - } - SelectionManager.m_Instance.ClearActiveSelection(); - m_PanelManager.GetPanel(m_CurrentGazeObject).CreatePopUp( - GlobalCommands.UploadToGenericCloud, (int)Cloud.None, -1); - EatGazeObjectInput(); - break; - } - case GlobalCommands.ExportAll: - { - StartCoroutine(LoadAndExportAll()); - break; - } - // Glen Keane request: a way to draw guidelines that can be toggled on and off - // at runtime. - case GlobalCommands.DraftingVisibility: - { - if (!Enum.IsDefined(typeof(DraftingVisibilityOption), iParam1)) - { - Debug.LogError("Unknown draft visibility value: " + iParam1); - return; - } - DraftingVisibilityOption option = (DraftingVisibilityOption)iParam1; - if (option != m_DraftingVisibility) - { - m_DraftingVisibility = option; - UpdateDraftingVisibility(); - } - break; - } - case GlobalCommands.MergeBrushStrokes: - { - // TODO Refactor with Load below - var index = iParam1; - var sketchSetType = (SketchSetType)iParam2; - SketchSet sketchSet = SketchCatalog.m_Instance.GetSet(sketchSetType); - SceneFileInfo rInfo = sketchSet.GetSketchSceneFileInfo(index); - if (rInfo != null) - { - MergeBrushStrokes(rInfo); - if (m_ControlsType != ControlsType.ViewingOnly) - { - EatGazeObjectInput(); - } - } - break; - } - case GlobalCommands.Load: - { - var index = iParam1; - var sketchSetType = (SketchSetType)iParam2; - SketchSet sketchSet = SketchCatalog.m_Instance.GetSet(sketchSetType); - SceneFileInfo rInfo = sketchSet.GetSketchSceneFileInfo(index); - if (rInfo != null) - { - LoadSketch(rInfo); - if (m_ControlsType != ControlsType.ViewingOnly) - { - EatGazeObjectInput(); - } - } - break; - } - case GlobalCommands.LoadNamedFile: - LoadNamed(sParam, iParam1 == (int)LoadSpeed.Quick, iParam2 != -1); - break; - case GlobalCommands.NewSketch: - NewSketch(fade: true); - Vector3 vTrashSoundPos = m_CurrentGazeRay.origin; - if (App.VrSdk.GetControllerDof() == VrSdk.DoF.Six) - { - vTrashSoundPos = InputManager.m_Instance.GetControllerPosition( - InputManager.ControllerName.Wand); - } - AudioManager.m_Instance.PlayTrashSound(vTrashSoundPos); - PromoManager.m_Instance.RequestAdvancedPanelsPromo(); - break; - case GlobalCommands.SymmetryPlane: - if (PointerManager.m_Instance.CurrentSymmetryMode != SymmetryMode.SinglePlane) - { - PointerManager.m_Instance.SetSymmetryMode(SymmetryMode.SinglePlane); - ControllerConsoleScript.m_Instance.AddNewLine("Mirror Enabled"); - } - else - { - PointerManager.m_Instance.SetSymmetryMode(SymmetryMode.None); - ControllerConsoleScript.m_Instance.AddNewLine("Mirror Off"); - } - break; - case GlobalCommands.MultiMirror: - if (PointerManager.m_Instance.CurrentSymmetryMode != SymmetryMode.MultiMirror) - { - PointerManager.m_Instance.SetSymmetryMode(SymmetryMode.MultiMirror); - ControllerConsoleScript.m_Instance.AddNewLine("Symmetry Enabled"); - } - else - { - PointerManager.m_Instance.SetSymmetryMode(SymmetryMode.None); - ControllerConsoleScript.m_Instance.AddNewLine("Symmetry Off"); - } - InputManager.m_Instance.TriggerHaptics(InputManager.ControllerName.Brush, 0.1f); - break; - case GlobalCommands.SymmetryTwoHanded: - if (PointerManager.m_Instance.CurrentSymmetryMode != SymmetryMode.TwoHanded) - { - PointerManager.m_Instance.SetSymmetryMode(SymmetryMode.TwoHanded); - ControllerConsoleScript.m_Instance.AddNewLine("Symmetry Enabled"); - } - else - { - PointerManager.m_Instance.SetSymmetryMode(SymmetryMode.None); - ControllerConsoleScript.m_Instance.AddNewLine("Symmetry Off"); - } - InputManager.m_Instance.TriggerHaptics(InputManager.ControllerName.Brush, 0.1f); - break; - case GlobalCommands.StraightEdge: - PointerManager.m_Instance.StraightEdgeModeEnabled = !PointerManager.m_Instance.StraightEdgeModeEnabled; - if (PointerManager.m_Instance.StraightEdgeModeEnabled) - { - ControllerConsoleScript.m_Instance.AddNewLine("Straight Edge On"); - } - else - { - ControllerConsoleScript.m_Instance.AddNewLine("Straight Edge Off"); - } - break; - case GlobalCommands.AutoOrient: - m_AutoOrientAfterRotation = !m_AutoOrientAfterRotation; - if (m_AutoOrientAfterRotation) - { - ControllerConsoleScript.m_Instance.AddNewLine("Auto-Orient On"); - } - else - { - ControllerConsoleScript.m_Instance.AddNewLine("Auto-Orient Off"); - } - break; - case GlobalCommands.Undo: - SketchMemoryScript.m_Instance.StepBack(); - break; - case GlobalCommands.Redo: - SketchMemoryScript.m_Instance.StepForward(); - break; - case GlobalCommands.AudioVisualization: // Intentionally blank. - break; - case GlobalCommands.ResetAllPanels: - m_PanelManager.ResetWandPanelsConfiguration(); - EatGazeObjectInput(); - break; - case GlobalCommands.SketchOrigin: - m_SketchSurfacePanel.EnableSpecificTool(BaseTool.ToolType.SketchOrigin); - EatGazeObjectInput(); - break; - case GlobalCommands.ViewOnly: - m_ViewOnly = !m_ViewOnly; - RequestPanelsVisibility(!m_ViewOnly); - PointerManager.m_Instance.RequestPointerRendering(!m_ViewOnly); - // TODO - decide if this is a permanent change - // With this line, you can't set a tool such as fly or teleport - // and switch to View Only mode as the mode change disables all tools - //m_SketchSurface.SetActive(!m_ViewOnly); - m_Decor.SetActive(!m_ViewOnly); - break; - case GlobalCommands.SaveGallery: - m_SketchSurfacePanel.EnableSpecificTool(BaseTool.ToolType.SaveIconTool); - break; - case GlobalCommands.DropCam: - // Want to enable this if in monoscopic or VR modes. - // TODO: seems odd to tie this switch to the controller type, should be based on some - // other build-time configuration setting. - if (App.VrSdk.GetControllerDof() != VrSdk.DoF.None) - { - m_DropCam.Show(!m_DropCam.gameObject.activeSelf); - } - break; - case GlobalCommands.AnalyticsEnabled_Deprecated: - break; - case GlobalCommands.ToggleAutosimplification: - QualityControls.AutosimplifyEnabled = !QualityControls.AutosimplifyEnabled; - break; - case GlobalCommands.Credits: - LoadSketch(new DiskSceneFileInfo(m_CreditsSketchFilename, embedded: true, readOnly: true)); - EatGazeObjectInput(); - break; - case GlobalCommands.AshleysSketch: - LoadSketch(new DiskSceneFileInfo(m_AshleysSketchFilename, embedded: true, readOnly: true)); - EatGazeObjectInput(); - break; - case GlobalCommands.FAQ: - OpenURLAndInformUser(m_HelpCenterURL); - break; - case GlobalCommands.ReleaseNotes: - OpenURLAndInformUser(m_ReleaseNotesURL); - break; - case GlobalCommands.ExportRaw: - if (!FileUtils.CheckDiskSpaceWithError(App.UserExportPath())) - { - return; - } - EatGazeObjectInput(); - StartCoroutine(ExportCoroutine()); - break; - case GlobalCommands.IRC: - if (m_IRCChatWidget == null) - { - GameObject widgetobject = (GameObject)Instantiate(m_IRCChatPrefab); - widgetobject.transform.parent = App.Instance.m_RoomTransform; - m_IRCChatWidget = widgetobject.GetComponent(); - m_IRCChatWidget.Show(true); - } - else - { - m_IRCChatWidget.Show(false); - m_IRCChatWidget = null; - } - break; - case GlobalCommands.YouTubeChat: - if (m_YouTubeChatWidget == null) - { - GameObject widgetobject = (GameObject)Instantiate(m_YouTubeChatPrefab); - widgetobject.transform.parent = App.Instance.m_RoomTransform; - m_YouTubeChatWidget = widgetobject.GetComponent(); - m_YouTubeChatWidget.Show(true); - } - else - { - m_YouTubeChatWidget.Show(false); - m_YouTubeChatWidget = null; - } - break; - case GlobalCommands.CameraOptions: - // If we're switching in to Camera mode, make sure Multicam is selected. - if (!m_PanelManager.CameraActive()) - { - SketchSurfacePanel.m_Instance.EnableSpecificTool(BaseTool.ToolType.MultiCamTool); - } - m_PanelManager.ToggleCameraPanels(); - PointerManager.m_Instance.EatLineEnabledInput(); - SketchSurfacePanel.m_Instance.EatToolsInput(); - break; - case GlobalCommands.ShowSketchFolder: - { - var index = iParam1; - var sketchSetType = (SketchSetType)iParam2; - SketchSet sketchSet = SketchCatalog.m_Instance.GetSet(sketchSetType); - SceneFileInfo rInfo = sketchSet.GetSketchSceneFileInfo(index); - EatGazeObjectInput(); - //launch external window and tell the user we did so - //this call is windows only - if ((Application.platform == RuntimePlatform.WindowsPlayer) || - (Application.platform == RuntimePlatform.WindowsEditor)) - { - OutputWindowScript.m_Instance.CreateInfoCardAtController( - InputManager.ControllerName.Brush, - kRemoveHeadsetFyi, fPopScalar: 0.5f); - System.Diagnostics.Process.Start("explorer.exe", - "/select," + rInfo.FullPath); - } - break; - } - case GlobalCommands.About: - OpenURLAndInformUser(m_ThirdPartyNoticesURL); - break; - case GlobalCommands.StencilsDisabled: - SketchMemoryScript.m_Instance.PerformAndRecordCommand(new StencilsVisibleCommand()); - break; - case GlobalCommands.StraightEdgeMeterDisplay: - PointerManager.m_Instance.StraightEdgeGuide.FlipMeter(); - break; - case GlobalCommands.Sketchbook: - m_PanelManager.ToggleSketchbookPanels(); - PointerManager.m_Instance.EatLineEnabledInput(); - SketchSurfacePanel.m_Instance.EatToolsInput(); - break; - case GlobalCommands.StraightEdgeShape: - // Previously experimental mode only. - // Untested and currently untriggerable. - PointerManager.m_Instance.StraightEdgeGuide.SetTempShape( - (StraightEdgeGuideScript.Shape)iParam1); - break; - case GlobalCommands.DeleteSketch: - { - var sketchSetType = (SketchSetType)iParam2; - SketchSet sketchSet = SketchCatalog.m_Instance.GetSet(sketchSetType); - sketchSet.DeleteSketch(iParam1); - DismissPopupOnCurrentGazeObject(false); - break; - } - case GlobalCommands.RenameSketch: - { - var sketchSetType = (SketchSetType)iParam2; - SketchSet sketchSet = SketchCatalog.m_Instance.GetSet(sketchSetType); - if (sketchSetType == SketchSetType.User) - { - sketchSet.RenameSketch(iParam1, KeyboardPopUpWindow.m_LastInput); - } - DismissPopupOnCurrentGazeObject(false); - break; - } - case GlobalCommands.RenameLayer: - { - var layer = App.Scene.GetCanvasByLayerIndex(iParam1); - App.Scene.RenameLayer(layer, KeyboardPopUpWindow.m_LastInput); - DismissPopupOnCurrentGazeObject(false); - break; - } - case GlobalCommands.ShowWindowGUI: - break; - case GlobalCommands.Disco: - LightsControlScript.m_Instance.DiscoMode = !LightsControlScript.m_Instance.DiscoMode; - break; - case GlobalCommands.AccountInfo: break; // Intentionally blank. - case GlobalCommands.LoginToGenericCloud: - { - var ident = App.GetIdentity((Cloud)iParam1); - if (!ident.LoggedIn) { ident.LoginAsync(); } - // iParam2 is being used as a UX flag. If not set to the default, it will cause the UI - // to lose focus. - if (iParam2 != -1) { EatGazeObjectInput(); } - break; - } - case GlobalCommands.LogOutOfGenericCloud: - { - var ident = App.GetIdentity((Cloud)iParam1); - if (ident.LoggedIn) { ident.Logout(); } - break; - } - case GlobalCommands.UploadToGenericCloud: - { - Cloud cloud = (Cloud)iParam1; - var ident = App.GetIdentity(cloud); - if (!ident.LoggedIn) - { - ident.LoginAsync(); - break; - } - SelectionManager.m_Instance.ClearActiveSelection(); - VrAssetService.m_Instance.UploadCurrentSketchAsync(cloud, isDemoUpload: false).AsAsyncVoid(); - EatGazeObjectInput(); - break; - } - case GlobalCommands.ViewOnlineGallery: - OpenURLAndInformUser(kTiltBrushGalleryUrl); - break; - case GlobalCommands.CancelUpload: - VrAssetService.m_Instance.CancelUpload(); - break; - case GlobalCommands.ViewLastUpload: - if (VrAssetService.m_Instance.LastUploadCompleteUrl != null) - { - var url = VrAssetService.m_Instance.LastUploadCompleteUrl; - App.OpenURL(url); - - // The upload flow is different on mobile and requires the user to manually accept - // that they'll go to the browser for publishing. In that case, we want to reset - // state when the leave to publish. This is automatically part of the - // UploadPopUpWindow state flow on PC. - if (App.Config.IsMobileHardware) - { - DismissPopupOnCurrentGazeObject(true); - } - } - break; - case GlobalCommands.ShowGoogleDrive: - string baseDriveUrl = "https://drive.google.com"; - string driveURL = !App.GoogleIdentity.LoggedIn ? baseDriveUrl : - string.Format( - "http://accounts.google.com/AccountChooser?Email={0}&continue={1}", - App.GoogleIdentity.Profile.email, baseDriveUrl); - OpenURLAndInformUser(driveURL); - break; - case GlobalCommands.GoogleDriveSync: - App.DriveSync.SyncEnabled = !App.DriveSync.SyncEnabled; - break; - case GlobalCommands.GoogleDriveSync_Folder: - App.DriveSync.ToggleSyncOnFolderOfType((DriveSync.SyncedFolderType)iParam1); - break; - case GlobalCommands.Duplicate: - { - int selectedVerts = SelectionManager.m_Instance.NumVertsInSelection; - - // TODO - this code has never taken imported models etc into account - if (PointerManager.m_Instance.CurrentSymmetryMode == SymmetryMode.MultiMirror) - { - selectedVerts *= PointerManager.m_Instance.CustomMirrorMatrices.Count; - } - - if (!SketchMemoryScript.m_Instance.MemoryWarningAccepted && - SketchMemoryScript.m_Instance.WillVertCountPutUsOverTheMemoryLimit(selectedVerts)) - { - AudioManager.m_Instance.PlayUploadCanceledSound(InputManager.Wand.Transform.position); - if (!m_PanelManager.MemoryWarningActive()) - { - m_PanelManager.ToggleMemoryWarningMode(); - } - } - else - { - ClipboardManager.Instance.DuplicateSelection( - stampMode: IsUserInteractingWithSelectionWidget()); - } - EatToolScaleInput(); - break; - } - case GlobalCommands.AdvancedPanelsToggle: - m_PanelManager.ToggleAdvancedPanels(); - // If we're now in basic mode, ensure we don't have advanced abilities. - if (!m_PanelManager.AdvancedModeActive()) - { - m_WidgetManager.StencilsDisabled = true; - m_WidgetManager.CameraPathsVisible = false; - App.Switchboard.TriggerStencilModeChanged(); - m_SketchSurfacePanel.EnsureUserHasBasicToolEnabled(); - if (PointerManager.m_Instance.CurrentSymmetryMode != SymmetryMode.None) - { - PointerManager.m_Instance.SetSymmetryMode(SymmetryMode.None, false); - } - } - PromoManager.m_Instance.RecordCompletion(PromoType.AdvancedPanels); - EatGazeObjectInput(); - break; - case GlobalCommands.Music: break; // Intentionally blank. - case GlobalCommands.ToggleGroupStrokesAndWidgets: - SelectionManager.m_Instance.ToggleGroupSelectedStrokesAndWidgets(); - EatToolScaleInput(); - break; - case GlobalCommands.SaveModel: - SaveModel(); - break; - case GlobalCommands.ViewPolyPage: - OpenURLAndInformUser(kPolyMainPageUri); - break; - case GlobalCommands.ViewPolyGallery: - OpenURLAndInformUser(kBlocksGalleryUrl); - break; - case GlobalCommands.ExportListed: - StartCoroutine(ExportListAndQuit()); - break; - case GlobalCommands.RenderCameraPath: - StartCoroutine(RenderPathAndQuit()); - break; - case GlobalCommands.ToggleProfiling: - ToggleProfiling(); - break; - case GlobalCommands.DoAutoProfile: - DoAutoProfile(); - break; - case GlobalCommands.DoAutoProfileAndQuit: - DoAutoProfileAndQuit(); - break; - case GlobalCommands.ToggleSettings: - m_PanelManager.ToggleSettingsPanels(); - PointerManager.m_Instance.EatLineEnabledInput(); - SketchSurfacePanel.m_Instance.EatToolsInput(); - break; - case GlobalCommands.SummonMirror: - PointerManager.m_Instance.BringSymmetryToUser(); - break; - case GlobalCommands.InvertSelection: - SelectionManager.m_Instance.InvertSelection(); - break; - case GlobalCommands.SelectAll: - SketchSurfacePanel.m_Instance.EnableSpecificTool(BaseTool.ToolType.SelectionTool); - SelectionManager.m_Instance.SelectAll(); - EatGazeObjectInput(); - break; - case GlobalCommands.FlipSelection: - SelectionManager.m_Instance.FlipSelection(); - break; - case GlobalCommands.ToggleBrushLab: - m_PanelManager.ToggleBrushLabPanels(); - PointerManager.m_Instance.EatLineEnabledInput(); - SketchSurfacePanel.m_Instance.EatToolsInput(); - break; - case GlobalCommands.ToggleCameraPostEffects: - CameraConfig.PostEffects = !CameraConfig.PostEffects; - break; - case GlobalCommands.ToggleWatermark: - if (PlayerPrefs.GetInt("Promo_Contribution", 0) == 0) - { - OutputWindowScript.m_Instance.CreateInfoCardAtController( - InputManager.ControllerName.Wand, - m_ContributionPromoText, fPopScalar: 1.0f); - PlayerPrefs.SetInt("Promo_Contribution", 1); - } - CameraConfig.Watermark = !CameraConfig.Watermark; - break; - case GlobalCommands.LoadConfirmComplexHigh: - IssueGlobalCommand(GlobalCommands.Load, iParam1, iParam2, null); - break; - case GlobalCommands.LoadConfirmComplex: - { - var index = iParam1; - var sketchSetType = (SketchSetType)iParam2; - bool loadSketch = true; - - // If the sketchbook is active, we may want to show a popup instead of load. - if (m_PanelManager.SketchbookActive()) - { - BasePanel sketchBook = m_PanelManager.GetSketchBookPanel(); - if (sketchBook != null) - { - // Get triangle count from cloud scene file info. - SketchSet sketchSet = SketchCatalog.m_Instance.GetSet(sketchSetType); - SceneFileInfo sfi = sketchSet.GetSketchSceneFileInfo(index); - int tris = sfi.TriangleCount ?? -1; - - // Show "this is bad" popup if we're over the triangle limit. - if (tris > QualityControls.m_Instance.AppQualityLevels.MaxPolySketchTriangles) - { - loadSketch = false; - sketchBook.CreatePopUp(GlobalCommands.LoadConfirmComplexHigh, iParam1, iParam2); - } - else if (tris > - QualityControls.m_Instance.AppQualityLevels.WarningPolySketchTriangles) - { - // Show, "this could be bad" popup if we're over the warning limit. - loadSketch = false; - sketchBook.CreatePopUp(GlobalCommands.Load, iParam1, iParam2); - } - } - } - - if (loadSketch) - { - IssueGlobalCommand(GlobalCommands.Load, iParam1, iParam2, null); - } - } - break; - case GlobalCommands.LoadConfirmUnsaved: - { - BasePanel sketchBook = m_PanelManager.GetSketchBookPanel(); - if ((sketchBook != null) && SketchMemoryScript.m_Instance.IsMemoryDirty()) - { - sketchBook.CreatePopUp(GlobalCommands.LoadWaitOnDownload, iParam1, iParam2, null); - } - else - { - IssueGlobalCommand(GlobalCommands.LoadWaitOnDownload, iParam1, iParam2, null); - } - } - break; - case GlobalCommands.LoadWaitOnDownload: - { - bool download = false; - if (iParam2 == (int)SketchSetType.Drive) - { - BasePanel sketchBook = m_PanelManager.GetSketchBookPanel(); - var googleSketchSet = SketchCatalog.m_Instance.GetSet(SketchSetType.Drive); - if (sketchBook != null - && googleSketchSet != null - && googleSketchSet.IsSketchIndexValid(iParam1) - && !googleSketchSet.GetSketchSceneFileInfo(iParam1).Available) - { - sketchBook.CreatePopUp(GlobalCommands.LoadConfirmComplex, iParam1, iParam2, null); - download = true; - } - } - if (!download) - { - IssueGlobalCommand(GlobalCommands.LoadConfirmComplex, iParam1, iParam2, null); - } - } - break; - case GlobalCommands.MemoryWarning: - if (iParam1 > 0) - { - SketchMemoryScript.m_Instance.MemoryWarningAccepted = true; - } - m_PanelManager.ToggleMemoryWarningMode(); - break; - case GlobalCommands.MemoryExceeded: - // If we're in the memory exceeded app state, exit. - if (App.CurrentState == App.AppState.MemoryExceeded) - { - App.Instance.SetDesiredState(App.AppState.Standard); - } - else - { - // If we're not in the full app state, just switch our panel mode. - m_PanelManager.ToggleMemoryWarningMode(); - } - break; - case GlobalCommands.ShowTos: - OpenURLAndInformUser(m_TosURL); - break; - case GlobalCommands.ShowPrivacy: - OpenURLAndInformUser(m_PrivacyURL); - break; - case GlobalCommands.ShowQuestSideLoading: - OpenURLAndInformUser(m_QuestSideLoadingHowToURL); - break; - case GlobalCommands.ShowContribution: - OpenURLAndInformUser(m_ContributionURL); - break; - case GlobalCommands.UnloadReferenceImageCatalog: - ReferenceImageCatalog.m_Instance.UnloadAllImages(); - break; - case GlobalCommands.ToggleCameraPathVisuals: - m_WidgetManager.CameraPathsVisible = !m_WidgetManager.CameraPathsVisible; - break; - case GlobalCommands.ToggleCameraPathPreview: - m_WidgetManager.FollowingPath = !m_WidgetManager.FollowingPath; - break; - case GlobalCommands.DeleteCameraPath: - { - var cameraPath = m_WidgetManager.GetCurrentCameraPath(); - GrabWidget cameraPathWidget = cameraPath == null ? null : cameraPath.m_WidgetScript; - m_WidgetManager.DeleteCameraPath(cameraPathWidget); - } - break; - case GlobalCommands.RecordCameraPath: - // Turn off MultiCam if we're going to record the camera path. - if (m_SketchSurfacePanel.GetCurrentToolType() == BaseTool.ToolType.MultiCamTool) - { - m_SketchSurfacePanel.EnableDefaultTool(); - } - CameraPathCaptureRig.RecordPath(); - EatGazeObjectInput(); - break; - case GlobalCommands.OpenScriptsCommandsList: - OpenURLAndInformUser($"http://localhost:{App.HttpServer.HttpPort}/help/commands"); - break; - case GlobalCommands.OpenScriptsList: - OpenURLAndInformUser($"http://localhost:{App.HttpServer.HttpPort}/scripts"); - break; - case GlobalCommands.OpenExampleScriptsList: - OpenURLAndInformUser($"http://localhost:{App.HttpServer.HttpPort}/examplescripts"); - break; - case GlobalCommands.RepaintOptions: break; // Intentionally blank. - case GlobalCommands.Null: break; // Intentionally blank. - default: - Debug.LogError($"Unrecognized command {rEnum}"); - break; - } - } - - private void LoadNamed(string path, bool quickload, bool additive) - { - var fileInfo = new DiskSceneFileInfo(path); - fileInfo.ReadMetadata(); - if (SaveLoadScript.m_Instance.LastMetadataError != null) - { - ControllerConsoleScript.m_Instance.AddNewLine( - string.Format("Error detected in sketch '{0}'.\nTry re-saving.", - fileInfo.HumanName)); - Debug.LogWarning(string.Format("Error reading metadata for {0}.\n{1}", - fileInfo.FullPath, SaveLoadScript.m_Instance.LastMetadataError)); - } - LoadSketch(fileInfo, quickload, additive); - if (m_ControlsType != ControlsType.ViewingOnly) - { - EatGazeObjectInput(); - } - } - - public void OpenURLAndInformUser(string url) - { - // On desktop - launch external browser and inform the user - // On mobile - the browser appears over the app - if (!App.Config.IsMobileHardware) - { - OutputWindowScript.m_Instance.CreateInfoCardAtController( - InputManager.ControllerName.Brush, - kRemoveHeadsetFyi, fPopScalar: 0.5f); - } - App.OpenURL(url); - EatGazeObjectInput(); - } - - public bool IsCommandActive(GlobalCommands rEnum, int iParam = -1) - { - switch (rEnum) - { - case GlobalCommands.StraightEdge: return PointerManager.m_Instance.StraightEdgeModeEnabled; - case GlobalCommands.StraightEdgeMeterDisplay: return PointerManager.m_Instance.StraightEdgeGuide.IsShowingMeter(); - case GlobalCommands.SymmetryPlane: return PointerManager.m_Instance.CurrentSymmetryMode == SymmetryMode.SinglePlane; - case GlobalCommands.MultiMirror: return PointerManager.m_Instance.CurrentSymmetryMode == SymmetryMode.MultiMirror; - case GlobalCommands.SymmetryTwoHanded: return PointerManager.m_Instance.CurrentSymmetryMode == SymmetryMode.TwoHanded; - case GlobalCommands.AutoOrient: return m_AutoOrientAfterRotation; - case GlobalCommands.AudioVisualization: return VisualizerManager.m_Instance.VisualsRequested; - case GlobalCommands.AdvancedPanelsToggle: return m_PanelManager.AdvancedModeActive(); - case GlobalCommands.Music: return VisualizerManager.m_Instance.VisualsRequested; - case GlobalCommands.DropCam: return m_DropCam.gameObject.activeSelf; - case GlobalCommands.ToggleAutosimplification: return QualityControls.AutosimplifyEnabled; - case GlobalCommands.DraftingVisibility: return m_DraftingVisibility == (DraftingVisibilityOption)iParam; - case GlobalCommands.Cameras: - return SketchSurfacePanel.m_Instance.GetCurrentToolType() == BaseTool.ToolType.AutoGif || - SketchSurfacePanel.m_Instance.GetCurrentToolType() == BaseTool.ToolType.ScreenshotTool; - case GlobalCommands.IRC: return m_IRCChatWidget != null; - case GlobalCommands.YouTubeChat: return m_YouTubeChatWidget != null; - case GlobalCommands.StencilsDisabled: return m_WidgetManager.StencilsDisabled; - case GlobalCommands.StraightEdgeShape: - // Previously experimental mode only. - // Untested and currently untriggerable. - return PointerManager.m_Instance.StraightEdgeGuide.TempShape == (StraightEdgeGuideScript.Shape)iParam || - (PointerManager.m_Instance.StraightEdgeGuide.TempShape == StraightEdgeGuideScript.Shape.None - && PointerManager.m_Instance.StraightEdgeGuide.CurrentShape == (StraightEdgeGuideScript.Shape)iParam); - case GlobalCommands.Disco: return LightsControlScript.m_Instance.DiscoMode; - case GlobalCommands.ToggleGroupStrokesAndWidgets: return SelectionManager.m_Instance.UngroupingAllowed; - case GlobalCommands.ToggleProfiling: return UnityEngine.Profiling.Profiler.enabled; - case GlobalCommands.ToggleCameraPostEffects: return CameraConfig.PostEffects; - case GlobalCommands.ToggleWatermark: return CameraConfig.Watermark; - case GlobalCommands.ToggleCameraPathVisuals: return m_WidgetManager.CameraPathsVisible; - case GlobalCommands.ToggleCameraPathPreview: return m_WidgetManager.FollowingPath; - case GlobalCommands.SelectCameraPath: - return m_WidgetManager.IsCameraPathAtIndexCurrent(iParam) && - m_WidgetManager.CameraPathsVisible; - case GlobalCommands.GoogleDriveSync_Folder: - return App.DriveSync.IsFolderOfTypeSynced((DriveSync.SyncedFolderType)iParam); - case GlobalCommands.GoogleDriveSync: return App.DriveSync.SyncEnabled; - case GlobalCommands.RecordCameraPath: return VideoRecorderUtils.ActiveVideoRecording != null; - } - return false; - } - - public void NewSketch(bool fade) - { - LightsControlScript.m_Instance.DiscoMode = false; - m_WidgetManager.FollowingPath = false; - SketchMemoryScript.m_Instance.ClearMemory(); - ControllerConsoleScript.m_Instance.AddNewLine("Sketch Cleared"); - ResetGrabbedPose(everything: true); - QualityControls.m_Instance.ResetAutoQuality(); - InputManager.m_Instance.TriggerHaptics(InputManager.ControllerName.Brush, 0.1f); - SaveLoadScript.m_Instance.ResetLastFilename(); - SelectionManager.m_Instance.RemoveFromSelection(false); - PointerManager.m_Instance.ResetSymmetryToHome(); - App.Scene.ResetLayers(notify: true); - ApiManager.Instance.ResetBrushTransform(); - - // If we've got the camera path tool active, switch back to the default tool. - // I'm doing this because if we leave the camera path tool active, the camera path - // panel shows the button highlighted, which affects the user's flow for being - // invited to start a path. It looks weird. - if (m_SketchSurfacePanel.ActiveToolType == BaseTool.ToolType.CameraPathTool) - { - m_SketchSurfacePanel.EnableDefaultTool(); - } - - m_WidgetManager.DestroyAllWidgets(); - if (LightsControlScript.m_Instance.LightsChanged || - SceneSettings.m_Instance.EnvironmentChanged) - { - SceneSettings.m_Instance.RecordSkyColorsForFading(); - SceneSettings.m_Instance.SetDesiredPreset( - SceneSettings.m_Instance.GetDesiredPreset(), skipFade: !fade); - } - // Blank the thumbnail position so that autosave won't save the thumbnail position to be - // the one from the old sketch. - SaveLoadScript.m_Instance.LastThumbnail_SS = null; - - // Re-set the quality level to reset simplification level - QualityControls.m_Instance.QualityLevel = QualityControls.m_Instance.QualityLevel; - - App.PolyAssetCatalog.ClearLoadingQueue(); - App.PolyAssetCatalog.UnloadUnusedModels(); - } - - private bool WorldIsReset(bool toSavedXf) - { - return App.Scene.Pose == - (toSavedXf ? SketchMemoryScript.m_Instance.InitialSketchTransform : TrTransform.identity); - } - - public bool IsCommandAvailable(GlobalCommands rEnum, int iParam = -1) - { - // TODO: hide gallery view / publish if there are no saved sketches - switch (rEnum) - { - case GlobalCommands.Undo: return SketchMemoryScript.m_Instance.CanUndo(); - case GlobalCommands.Redo: return SketchMemoryScript.m_Instance.CanRedo(); - case GlobalCommands.Save: - bool canSave = - SaveLoadScript.m_Instance.SceneFile.Valid && - SaveLoadScript.m_Instance.IsSavingAllowed(); - return canSave && (!WorldIsReset(toSavedXf: true) || - (SketchHasChanges() && SketchMemoryScript.m_Instance.IsMemoryDirty())); - case GlobalCommands.SaveOptions: - case GlobalCommands.SaveNew: - case GlobalCommands.SaveGallery: - return SketchHasChanges(); - case GlobalCommands.SaveOnLocalChanges: - if (!SaveLoadScript.m_Instance.SceneFile.Valid) - { - // No save file, but something has changed. - return SketchHasChanges(); - } - else - { - if (SaveLoadScript.m_Instance.CanOverwriteSource) - { - // Save file, and it's our file. Whether we have changes is irrelevant. - return true; - } - // Save file, but it's not our file. Only make a copy if there are local changes. - return SketchMemoryScript.m_Instance.IsMemoryDirty(); - } - case GlobalCommands.UploadToGenericCloud: - return SketchMemoryScript.m_Instance.HasVisibleObjects() || - m_WidgetManager.ExportableModelWidgets.Any(w => w.gameObject.activeSelf) || - m_WidgetManager.ImageWidgets.Any(w => w.gameObject.activeSelf) || - VrAssetService.m_Instance.UploadProgress >= 1.0f || - VrAssetService.m_Instance.LastUploadFailed; - case GlobalCommands.SaveAndUpload: - return App.GoogleIdentity.LoggedIn && - (VrAssetService.m_Instance.UploadProgress <= 0.0f) && - IsCommandAvailable(GlobalCommands.UploadToGenericCloud); - case GlobalCommands.NewSketch: - return SketchHasChanges(); - case GlobalCommands.Credits: - case GlobalCommands.AshleysSketch: - return !SketchHasChanges() && !SketchMemoryScript.m_Instance.IsMemoryDirty(); - case GlobalCommands.Tiltasaurus: return TiltBrush.Tiltasaurus.m_Instance.TiltasaurusAvailable(); - case GlobalCommands.ExportRaw: - return SketchMemoryScript.m_Instance.HasVisibleObjects() || - m_WidgetManager.ModelWidgets.Any(w => w.gameObject.activeSelf) || - m_WidgetManager.ImageWidgets.Any(w => w.gameObject.activeSelf); - case GlobalCommands.ResetAllPanels: return m_PanelManager.PanelsHaveBeenCustomized(); - case GlobalCommands.Duplicate: return ClipboardManager.Instance.CanCopy; - case GlobalCommands.ToggleGroupStrokesAndWidgets: return SelectionManager.m_Instance.SelectionCanBeGrouped; - case GlobalCommands.SaveModel: return SelectionManager.m_Instance.HasSelection; - case GlobalCommands.SummonMirror: - return PointerManager.m_Instance.CurrentSymmetryMode != - SymmetryMode.None; - case GlobalCommands.InvertSelection: - case GlobalCommands.FlipSelection: - return SelectionManager.m_Instance.HasSelection; - case GlobalCommands.SelectAll: - return SketchMemoryScript.m_Instance.HasVisibleObjects() || - m_WidgetManager.HasSelectableWidgets(); - case GlobalCommands.UnloadReferenceImageCatalog: - return ReferenceImageCatalog.m_Instance.AnyImageValid(); - case GlobalCommands.ToggleCameraPathPreview: - return m_WidgetManager.CanRecordCurrentCameraPath(); - case GlobalCommands.DeleteCameraPath: - return CameraPathCaptureRig.Enabled && m_WidgetManager.AnyActivePathHasAKnot(); - case GlobalCommands.ToggleCameraPathVisuals: - return m_WidgetManager.AnyActivePathHasAKnot(); - case GlobalCommands.GoogleDriveSync: - return App.GoogleIdentity.LoggedIn; - case GlobalCommands.RecordCameraPath: return m_WidgetManager.CameraPathsVisible; - } - return true; - } - - public bool SketchHasChanges() - { - if (SceneSettings.m_Instance.IsTransitioning) { return false; } - return SketchMemoryScript.m_Instance.HasVisibleObjects() || - SceneSettings.m_Instance.EnvironmentChanged || - LightsControlScript.m_Instance.LightsChanged || - m_WidgetManager.ModelWidgets.Any(w => w.gameObject.activeSelf) || - m_WidgetManager.LightWidgets.Any(w => w.gameObject.activeSelf) || - m_WidgetManager.StencilWidgets.Any(w => w.gameObject.activeSelf) || - m_WidgetManager.ImageWidgets.Any(w => w.gameObject.activeSelf) || - m_WidgetManager.VideoWidgets.Any(w => w.gameObject.activeSelf) || - m_WidgetManager.AnyCameraPathWidgetsActive; - } - - public void OpenPanelOfType(BasePanel.PanelType type, TrTransform trSpawnXf) - { - m_PanelManager.OpenPanel(type, trSpawnXf); - EatGazeObjectInput(); - } - - public void RestoreFloatingPanels() - { - if (!m_SketchSurfacePanel.ActiveTool.HidePanels()) - { - m_PanelManager.RestoreHiddenPanels(); - } - } - - public void UpdateDraftingVisibility() - { - float value = 0; - switch (m_DraftingVisibility) - { - case DraftingVisibilityOption.Visible: - value = 1; - break; - case DraftingVisibilityOption.Transparent: - value = .5f; - break; - case DraftingVisibilityOption.Hidden: - value = 0; - break; - } - Shader.SetGlobalFloat("_DraftingVisibility01", value); - } - - private void ToggleProfiling() - { - if (Debug.isDebugBuild && ProfileDisplay.Instance != null) - { - ProfileDisplay.Instance.gameObject.SetActive(UnityEngine.Profiling.Profiler.enabled); - } - if (UnityEngine.Profiling.Profiler.enabled) - { - ProfilingManager.Instance.StopProfiling(); - } - else - { - ProfilingManager.Instance.StartProfiling(App.UserConfig.Profiling.ProfilingMode); - } - } - - private void DoAutoProfile() - { - StartCoroutine(DoProfiling()); - } - - private void DoAutoProfileAndQuit() - { - StartCoroutine(DoProfiling(andQuit: true)); - } - - private IEnumerator DoProfiling(bool andQuit = false) - { - TrTransform oldWandPose = TrTransform.FromTransform(InputManager.Wand.Geometry.transform); - TrTransform oldBrushPose = TrTransform.FromTransform(InputManager.Brush.Geometry.transform); - - App.AppState oldState = App.CurrentState; - App.Instance.SetDesiredState(App.AppState.AutoProfiling); - while (App.CurrentState != App.AppState.AutoProfiling) - { - yield return null; - } - - TrTransform camPose = App.Scene.Pose * SaveLoadScript.m_Instance.ReasonableThumbnail_SS; - camPose.ToTransform(App.VrSdk.GetVrCamera().transform); - float controllerDirection = App.UserConfig.Profiling.ShowControllers ? 1f : -1f; - Vector3 roffset = Camera.main.transform.right * 2f; - Vector3 fOffset = Camera.main.transform.forward * 4f * controllerDirection; - InputManager.Brush.Geometry.transform.position = Camera.main.transform.position + roffset + fOffset; - InputManager.Brush.Geometry.transform.rotation = Camera.main.transform.rotation; - InputManager.Wand.Geometry.transform.position = Camera.main.transform.position - roffset + fOffset; - InputManager.Wand.Geometry.transform.rotation = Camera.main.transform.rotation; - m_PanelManager.LockPanelsToController(); - - ProfilingManager.Instance.StartProfiling(App.UserConfig.Profiling.ProfilingMode); - yield return new WaitForSeconds(App.UserConfig.Profiling.Duration); - ProfilingManager.Instance.StopProfiling(); - - if (App.UserConfig.Profiling.TakeScreenshot) - { - GameObject camObj = new GameObject("ScreenShotter"); - Camera cam = camObj.AddComponent(); - cam.CopyFrom(App.VrSdk.GetVrCamera()); - cam.stereoTargetEye = StereoTargetEyeMask.None; - cam.clearFlags = CameraClearFlags.SolidColor; - camPose.ToTransform(camObj.transform); - int res = App.UserConfig.Profiling.ScreenshotResolution; - RenderTexture renderTexture = RenderTexture.GetTemporary(res, res, 24); - try - { - cam.targetTexture = renderTexture; - cam.Render(); - RenderTexture prev = RenderTexture.active; - RenderTexture.active = renderTexture; - var texture = new Texture2D(res, res, TextureFormat.RGB24, false); - texture.ReadPixels(new Rect(0, 0, texture.width, texture.height), 0, 0); - RenderTexture.active = prev; - byte[] jpegBytes = texture.EncodeToJPG(); - string filename = - Path.GetFileNameWithoutExtension(SaveLoadScript.m_Instance.SceneFile.FullPath); - File.WriteAllBytes(Path.Combine(App.UserPath(), filename + ".jpg"), jpegBytes); - } - finally - { - Destroy(camObj); - RenderTexture.ReleaseTemporary(renderTexture); - } - } - - oldWandPose.ToTransform(InputManager.Wand.Geometry.transform); - oldBrushPose.ToTransform(InputManager.Brush.Geometry.transform); - App.Instance.SetDesiredState(oldState); - - if (andQuit) - { - QuitApp(); - } - } - } - -} // namespace TiltBrush +// Copyright 2020 The Tilt Brush Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// 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; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using TiltBrush.Layers; +using UnityEngine; +using UnityEngine.InputSystem; +using SymmetryMode = TiltBrush.PointerManager.SymmetryMode; + +namespace TiltBrush +{ + + public class SketchControlsScript : MonoBehaviour + { + // TODO L10n + public const string kRemoveHeadsetFyi = "Remove headset to view."; + + private string m_OpenBrushGalleryUrl => $"{VrAssetService.m_Instance.IcosaHomePage}/openbrush"; + private string m_BlocksGalleryUrl => $"{VrAssetService.m_Instance.IcosaHomePage}/blocks"; + + static public SketchControlsScript m_Instance; + static bool sm_enableGrabHaptics = true; + + // ------------------------------------------------------------ + // Constants and types + // ------------------------------------------------------------ + + public enum GlobalCommands + { + Null, + Save, + SaveNew, + Load, + NewSketch, + StraightEdge, + AutoOrient, + Undo, + Redo, + Tiltasaurus, + LightingHdr, + AudioVisualization, + ResetAllPanels, + SketchOrigin, + SymmetryPlane, + MultiMirror, + ViewOnly, + SaveGallery, + LightingLdr, + ShowSketchFolder, + About, + LoadNamedFile, // iParam1 : (optional) - send through a LoadSpeed as int + DropCam, + CuratedGallery, + Unused_UploadToCloud, + AnalyticsEnabled_Deprecated, + Credits, + LogOutOfGenericCloud, + DraftingVisibility, + DeleteSketch, + ShowWindowGUI, + MorePanels, + Cameras, + FAQ, + ExportRaw, + IRC, + YouTubeChat, + CameraOptions, + StencilsDisabled, + AdvancedTools, + FloatingPanelsMode, + StraightEdgeMeterDisplay, + Sketchbook, + ExportAll, + Lights, + SaveAndUpload, + StraightEdgeShape, + SaveOptions, + SketchbookMenu, + Disco, + ViewOnlineGallery, + CancelUpload, + AdvancedPanelsToggle, + Music, + Duplicate, + ToggleGroupStrokesAndWidgets, + SaveModel, + ViewIcosaHomePage, + ViewBlocksGallery, + ExportListed, + RenderCameraPath, + ToggleProfiling, + DoAutoProfile, + DoAutoProfileAndQuit, + ToggleSettings, + SummonMirror, + InvertSelection, + SelectAll, + FlipSelection, + ToggleBrushLab, + ReleaseNotes, + ToggleCameraPostEffects, + ToggleWatermark, + AccountInfo, + // LoadConfirmUnsaved -> LoadWaitOnDownload -> LoadConfirmComplex -> LoadComplexHigh -> Load + LoadConfirmUnsaved, + LoadConfirmComplex, + MemoryWarning, + MemoryExceeded, + ViewLastUpload, + LoadConfirmComplexHigh, + ShowTos, + ShowPrivacy, + ShowQuestSideLoading, + AshleysSketch, + UnloadReferenceImageCatalog, + SaveOnLocalChanges, + ToggleCameraPathVisuals, + ToggleCameraPathPreview, + DeleteCameraPath, + RecordCameraPath, + SelectCameraPath, + ToggleAutosimplification, + ShowGoogleDrive, + GoogleDriveSync_Folder, // iParam1: folder id as DriveSync.SyncedFolderType + GoogleDriveSync, + LoginToGenericCloud, // iParam1: Cloud enum + UploadToGenericCloud, // iParam1: Cloud enum + LoadWaitOnDownload, + SignOutConfirm, + ReadOnlyNotice, + ShowContribution, + + // Open Brush Reserved Enums 1000-1999 + LanguagePopup = 1000, + + RenameSketch = 5200, + OpenLayerOptionsPopup = 5201, + RenameLayer = 5202, + LoginToIcosa = 5600, + OpenDirectorChooserPopup = 5800, + OpenScriptsCommandsList = 6000, + OpenScriptsList = 6001, + OpenExampleScriptsList = 6002, + SymmetryTwoHanded = 6003, + OpenColorOptionsPopup = 7000, + ChangeSnapAngle = 8000, + MergeBrushStrokes = 10000, + RepaintOptions = 11500, + OpenNumericInputPopup = 12000 + } + + public enum ControlsType + { + KeyboardMouse, + SixDofControllers, + ViewingOnly + } + + public enum DraftingVisibilityOption + { + Visible, + Transparent, + Hidden + } + + public enum InputState + { + Standard, + Pan, + Rotation, + HeadLock, + ControllerLock, + PushPull, + BrushSize, + Save, + Load, + Num + } + + public enum LoadSpeed + { + Normal = -1, + Quick = 1, + } + + const float kControlPointHistoryMaxTime = 0.1f; + + class GazeResult + { + public bool m_HitWithGaze; + public bool m_HitWithController; + // ReSharper disable once NotAccessedField.Local + public bool m_WithinView; + public float m_ControllerDistance; + public Vector3 m_GazePosition; + public Vector3 m_ControllerPosition; + public InputManager.ControllerName m_ControllerName; + } + + class GrabWidgetControllerInfo + { + public InputManager.ControllerName m_Name; + /// Transform of controller at the time the grab started + public TrTransform m_BaseControllerXf; + /// "local" transform of widget (relative to controller), at the time the grab started. + /// The widget isn't parented to the controller, but if it were, this would be its transform. + public TrTransform m_BaseWidgetXf_LS; + } + + struct GrabWidgetHoldPoint + { + // ReSharper disable once NotAccessedField.Local + public InputManager.ControllerName m_Name; + public float m_BirthTime; + public Vector3 m_Pos; // where controller is holding the widget + public Quaternion m_Rot; + } + + class InputStateConfig + { + public bool m_AllowDrawing; + public bool m_AllowMovement; + public bool m_ShowGizmo; + } + + enum FadeState + { + None, + FadeOn, + FadeOff + } + + enum GrabWidgetState + { + None, + OneHand, + TwoHands + } + + enum GrabWorldState + { + Normal, + ResettingTransform, + ResetDone + } + + private enum WorldTransformResetState + { + Default, + Requested, + FadingToBlack, + FadingToScene, + } + + enum RotationType + { + All, + RollOnly + } + + enum GrabIntersectionState + { + RequestIntersections, + ReadBrush, + ReadWand + } + + // ------------------------------------------------------------ + // Inspector data (read-only even if public) + // ------------------------------------------------------------ + + public GameObject m_SketchSurface; + public SketchMemoryScript.PlaybackMode m_DefaultSketchPlaybackMode; + public float m_GazeMaxAngleFromPointing = 85.0f; + public float m_GazeMaxAngleFacingToForward = 80.0f; + + [SerializeField] bool m_AtlasIconTextures; + + [SerializeField] SaveIconTool m_SaveIconTool; + [SerializeField] DropCamWidget m_DropCam; + [SerializeField] string m_CreditsSketchFilename; + [SerializeField] string m_AshleysSketchFilename; + [SerializeField] float m_DefaultSketchLoadSpeed; + [SerializeField] GameObject m_TransformGizmoPrefab; + + [SerializeField] GameObject m_RotationIconPrefab; + [SerializeField] float m_GazeMaxAngleFromFacing = 70.0f; + [SerializeField] float m_GazeMaxDistance = 10.0f; + [SerializeField] float m_GazeControllerPointingDistance; + [SerializeField] float m_GazePanelDectivationDelay = 0.25f; + + [SerializeField] GameObject m_UIReticle; + [SerializeField] GameObject m_UIReticleMobile; + [SerializeField] GameObject m_UIReticleSixDofController; + + [SerializeField] float m_DoubleTapWindow; + [SerializeField] float m_PushPullScale; + [SerializeField] RotationCursorScript m_RotationCursor; + [SerializeField] float m_RotationMaxAngle; + + [SerializeField] float m_RotationScalar; + [SerializeField] float m_RotationRollScalar; + [SerializeField] float m_PanScalar; + + [SerializeField] float m_AdjustToolSizeScalar; + + [SerializeField] GameObject m_IRCChatPrefab; + [SerializeField] GameObject m_YouTubeChatPrefab; + [SerializeField] GameObject m_Decor; + [SerializeField] BaseTool.ToolType m_InitialTool = BaseTool.ToolType.SketchSurface; + [SerializeField] string m_ReleaseNotesURL; + [SerializeField] string m_HelpCenterURL; + [SerializeField] string m_ThirdPartyNoticesURL; + [SerializeField] string m_TosURL; + [SerializeField] string m_PrivacyURL; + [SerializeField] string m_QuestSideLoadingHowToURL; + + [Multiline] + [SerializeField] string m_ContributionPromoText; + [SerializeField] string m_ContributionURL; + + [SerializeField] float m_WorldTransformMinScale = .1f; + [SerializeField] float m_WorldTransformMaxScale = 10.0f; + + [Header("Undo/Redo Hold")] + [SerializeField] float m_UndoRedoHold_DurationBeforeStart; + [SerializeField] float m_UndoRedoHold_RepeatInterval; + + [Header("Pin Cushion")] + [SerializeField] GameObject m_PinCushionPrefab; + + [Header("Grabbing and tossing")] + [SerializeField] float m_GrabWorldFadeSpeed = 8.0f; + [SerializeField] Color m_GrabWorldGridColor = new Color(0.0f, 1.0f, 1.0f, 0.2f); + [SerializeField] ControllerGrabVisuals m_ControllerGrabVisuals; + [SerializeField] float m_WidgetGpuIntersectionRadius; + + [Header("Saving")] + [SerializeField] int m_NumStrokesForSaveIcon = 50; + + [NonSerialized] public Color m_GrabHighlightActiveColor; + [NonSerialized] public bool m_DisableWorldGrabbing = false; + + /// Throwing an object faster than this means it's a "toss". Units are m/s. + public float m_TossThresholdMeters = 3f; + /// Angular motion contributes more towards the toss velocity the larger the object is; + /// or rather, the larger the distance between the grab point and the object's center. + /// To prevent large objects from being too-easily-tossed, bound that distance. + public float m_TossMaxPivotDistMeters = 0.33f; + + // ------------------------------------------------------------ + // Internal data + // ------------------------------------------------------------ + + private SketchSurfacePanel m_SketchSurfacePanel; + private SketchMemoryScript.PlaybackMode m_SketchPlaybackMode; + private GameObject m_TransformGizmo; + private TransformGizmoScript m_TransformGizmoScript; + private GameObject m_RotationIcon; + private float m_MouseDeltaX; + private float m_MouseDeltaY; + private float m_MouseDeltaXScaled; + private float m_MouseDeltaYScaled; + private float m_PositionOffsetResetTapTime; + private bool m_EatToolScaleInput; + + private PanelManager m_PanelManager; + private WidgetManager m_WidgetManager; + private PinCushion m_PinCushion; + private bool m_EatPinCushionInput; + + // This is the gaze that was used to compute m_CurrentGazeHitPoint. + // It is not a general substitute for ViewpointScript.Gaze. + private Ray m_CurrentGazeRay; + private Quaternion m_CurrentHeadOrientation; + private GazeResult[] m_GazeResults; + private int m_CurrentGazeObject; + private bool m_EatInputGazeObject; + private Vector3 m_CurrentGazeHitPoint; + private Ray m_GazeControllerRay; + private Ray m_GazeControllerRayActivePanel; + private bool m_ForcePanelActivation = false; + private float m_GazePanelDectivationCountdown; + private bool m_PanelsVisibilityRequested; + + // Previously Experimental-Model only + private bool m_HeadOffset; + + float m_UndoHold_Timer; + float m_RedoHold_Timer; + + // Grab world member variables. + struct GrabState + { + public InputManager.ControllerName name; + public TrTransform grabTransform; + public bool grabbingWorld; + public bool grabbingGroup; + public bool startedGrabInsideWidget; + public bool eatInput; + private GrabWidget lastWidgetIntersect; + + public void SetHadBestGrabAndTriggerHaptics(GrabWidgetData data) + { + bool dormant = WidgetManager.m_Instance.WidgetsDormant; + if (data != null && !data.m_WidgetScript.AllowDormancy) + { + dormant = false; + } + GrabWidget newInsideWidget = (data != null && !dormant) ? data.m_WidgetScript : null; + if (sm_enableGrabHaptics && newInsideWidget != lastWidgetIntersect) + { + // state changed + if (newInsideWidget != null) + { + // transitioning in + InputManager.m_Instance.TriggerHaptics(name, data.m_WidgetScript.HapticDuration); + } + else + { + // transitioning out + InputManager.m_Instance.TriggerHaptics(name, 0.03f); + } + } + lastWidgetIntersect = newInsideWidget; + } + + public void ClearInsideWidget() + { + lastWidgetIntersect = null; + } + } + private GrabState m_GrabBrush = new GrabState { name = InputManager.ControllerName.Brush }; + private GrabState m_GrabWand = new GrabState { name = InputManager.ControllerName.Wand }; + + private WorldTransformResetState m_WorldTransformResetState = WorldTransformResetState.Default; + private TrTransform m_WorldTransformResetXf = TrTransform.identity; // set when reset requested + private GrabWorldState m_GrabWorldState = GrabWorldState.Normal; + private float m_WorldTransformFadeAmount; + private bool m_AllowWorldTransformLastFrame = false; + private bool m_WorldBeingGrabbed; + private TrTransform m_xfDropCamReset_RS; + + struct GpuIntersectionResult + { + public GpuIntersector.FutureModelResult result; + public List resultList; + } + private Queue m_BrushResults; + private Queue m_WandResults; + private int m_WidgetGpuIntersectionLayer; + + private GrabWidget m_CurrentGrabWidget; + private GrabWidget m_MaybeDriftingGrabWidget; // use only to clear drift + + // References to widgets, cached in the UpdateGrab_None, to be used by helper functions + // for the remainder of the frame. + private GrabWidget m_PotentialGrabWidgetBrush; + private GrabWidget m_PotentialGrabWidgetWand; + + // Flags for the explaining if the m_PotentialGrabWidget_x widgets are able to be interacted with. + // Cached in the UpdateGrab_None, used for the remainder of the frame. + private bool m_PotentialGrabWidgetBrushValid; + private bool m_PotentialGrabWidgetWandValid; + + // References to widget metadata, cached in UpdateGrab_None, to be re-used on "off frames" + // when the GPU intersector is not refreshing the nearest widget to the respective controller. + private GrabWidgetData m_BackupBrushGrabData; + private GrabWidgetData m_BackupWandGrabData; + + private GrabWidgetState m_GrabWidgetState; + private GrabWidgetControllerInfo m_GrabWidgetOneHandInfo; + private TrTransform m_GrabWidgetTwoHandBrushPrev; + private TrTransform m_GrabWidgetTwoHandWandPrev; + private Queue m_GrabWidgetHoldHistory; + + private Quaternion m_RotationOrigin; + private Vector2 m_RotationCursorOffset; + + private bool m_RotationRollActive; + private float m_RotationResetTapTime; + + private RotationType m_CurrentRotationType; + private bool m_AutoOrientAfterRotation; + + private Vector3 m_SurfaceForward; + private Vector3 m_SurfaceRight; + private Vector3 m_SurfaceUp; + + private Vector3 m_SurfaceLockOffset; + private Vector3 m_SurfaceLockBaseSurfacePosition; + private Vector3 m_SurfaceLockBaseControllerPosition; + private Quaternion m_SurfaceLockBaseHeadRotation; + private Quaternion m_SurfaceLockBaseControllerRotation; + private Quaternion m_SurfaceLockBaseSurfaceRotation; + private InputManager.ControllerName m_SurfaceLockActingController; + private float m_SurfaceLockControllerBaseScalar; + private float m_SurfaceLockControllerScalar; + + private bool m_PositioningPanelWithHead; + private Quaternion m_PositioningPanelBaseHeadRotation; + private Vector3 m_PositioningPanelOffset; + private float m_PositioningTimer; + private float m_PositioningSpeed; + + private DraftingVisibilityOption m_DraftingVisibility = DraftingVisibilityOption.Visible; + + private Vector3 m_SketchOrigin; + + private ControlsType m_ControlsType; + private GrabWidget m_IRCChatWidget; + private GrabWidget m_YouTubeChatWidget; + private MultiCamCaptureRig m_MultiCamCaptureRig; + private CameraPathCaptureRig m_CameraPathCaptureRig; + + private bool m_ViewOnly = false; + + private InputState m_CurrentInputState; + private InputStateConfig[] m_InputStateConfigs; + + private GrabIntersectionState m_CurrentGrabIntersectionState; + + private float m_WorldTransformSpeedSmoothed; + + // ------------------------------------------------------------ + // Properties and events + // ------------------------------------------------------------ + + public MultiCamCaptureRig MultiCamCaptureRig + { + get { return m_MultiCamCaptureRig; } + } + + public CameraPathCaptureRig CameraPathCaptureRig + { + get { return m_CameraPathCaptureRig; } + } + + public ControllerGrabVisuals ControllerGrabVisuals + { + get { return m_ControllerGrabVisuals; } + } + + public SketchMemoryScript.PlaybackMode SketchPlaybackMode + { + get { return m_SketchPlaybackMode; } + set { m_SketchPlaybackMode = value; } + } + + public Transform m_Canvas + { + get { return App.Instance.m_CanvasTransform; } + } + + public ControlsType ActiveControlsType + { + get { return m_ControlsType; } + set { m_ControlsType = value; } + } + + public float WorldTransformMinScale + { + get + { + return App.UserConfig.Flags.UnlockScale ? m_WorldTransformMinScale * 0.01f : + m_WorldTransformMinScale; + } + } + + public float WorldTransformMaxScale + { + get + { + return App.UserConfig.Flags.UnlockScale ? m_WorldTransformMaxScale * 10.0f : + m_WorldTransformMaxScale; + } + } + + public void SetInitialTool(BaseTool.ToolType rType) + { + m_InitialTool = rType; + } + + public void SetInFreePaintMode(bool bFreePaint) + { + m_SketchSurfacePanel.SetInFreePaintMode(bFreePaint); + } + + public float GazeMaxDistance + { + get { return m_GazeMaxDistance; } + } + + public InputManager.ControllerName OneHandGrabController + { + get + { + return m_CurrentGrabWidget != null ? + m_GrabWidgetOneHandInfo.m_Name : + InputManager.ControllerName.None; + } + } + + public InputManager.ControllerName PotentialOneHandGrabController(GrabWidget widget) + { + if (m_PotentialGrabWidgetBrush == widget) + { + return InputManager.ControllerName.Brush; + } + else if (m_PotentialGrabWidgetWand == widget) + { + return InputManager.ControllerName.Wand; + } + return OneHandGrabController; + } + + public Vector3 GetSurfaceForward() { return m_SurfaceForward; } + public Vector3 GetSurfaceUp() { return m_SurfaceUp; } + public Vector3 GetSurfaceRight() { return m_SurfaceRight; } + public Vector3 GetSketchOrigin() { return m_SketchOrigin; } + public float GetDefaultSketchLoadSpeed() { return m_DefaultSketchLoadSpeed; } + public Quaternion GetCurrentHeadOrientation() { return m_CurrentHeadOrientation; } + public Vector3 GetUIReticlePos() { return m_UIReticle.transform.position; } + public Vector3 GetSweetSpotPos() { return m_PanelManager.m_SweetSpot.transform.position; } + public void SetSketchOrigin(Vector3 vOrigin) { m_SketchOrigin = vOrigin; } + + public void EatGazeObjectInput() + { + m_EatInputGazeObject = true; + m_GazePanelDectivationCountdown = 0.0f; + PointerManager.m_Instance.EatLineEnabledInput(); + SketchSurfacePanel.m_Instance.EatToolsInput(); + } + public void EatToolScaleInput() { m_EatToolScaleInput = true; } + public void EatGrabInput() + { + m_GrabWand.eatInput = true; + m_GrabBrush.eatInput = true; + } + + public bool ShouldRespondToPadInput(InputManager.ControllerName name) + { + if (name == InputManager.ControllerName.Brush && m_CurrentGazeObject != -1) + { + return m_PanelManager.GetPanel(m_CurrentGazeObject).BrushPadAnimatesOnHover(); + } + return !m_EatToolScaleInput && SketchSurfacePanel.m_Instance.CanAdjustToolSize(); + } + public void ForcePanelActivation(bool bForce) + { + m_ForcePanelActivation = bForce; + if (m_ForcePanelActivation) + { + m_GazePanelDectivationCountdown = m_GazePanelDectivationDelay; + } + } + public bool IsUserInteractingWithUI() + { + return (m_CurrentGazeObject != -1) || (m_GazePanelDectivationCountdown > 0.0f); + } + public bool IsUIBlockingUndoRedo() + { + if (m_CurrentGazeObject != -1) + { + return m_PanelManager.GetPanel(m_CurrentGazeObject).UndoRedoBlocked(); + } + return false; + } + public bool IsUserAbleToInteractWithAnyWidget() + { + return IsUserInteractingWithAnyWidget() || + (m_PotentialGrabWidgetBrush != null && m_PotentialGrabWidgetBrushValid) || + (m_PotentialGrabWidgetWand != null && m_PotentialGrabWidgetWandValid); + } + public bool IsUserInteractingWithAnyWidget() { return m_CurrentGrabWidget != null; } + public bool IsUserGrabbingAnyPanel() + { + return (m_CurrentGrabWidget != null && m_CurrentGrabWidget is PanelWidget); + } + public bool IsUsersBrushIntersectingWithSelectionWidget() + { + return (m_PotentialGrabWidgetBrush != null && + m_PotentialGrabWidgetBrushValid && + m_PotentialGrabWidgetBrush is SelectionWidget); + } + public bool IsUserIntersectingWithSelectionWidget() + { + return IsUsersBrushIntersectingWithSelectionWidget() || + (m_PotentialGrabWidgetWand != null && + m_PotentialGrabWidgetWandValid && + m_PotentialGrabWidgetWand is SelectionWidget); + } + public bool IsUserInteractingWithSelectionWidget() + { + return (m_CurrentGrabWidget != null && m_CurrentGrabWidget is SelectionWidget); + } + + public bool IsUserGrabbingWorld() { return m_GrabWand.grabbingWorld || m_GrabBrush.grabbingWorld; } + public bool IsUserGrabbingWorldWithBrushHand() { return m_GrabBrush.grabbingWorld; } + public bool IsUserTransformingWorld() { return m_GrabWand.grabbingWorld && m_GrabBrush.grabbingWorld; } + public float GetGazePanelActivationRatio() { return m_GazePanelDectivationCountdown / m_GazePanelDectivationDelay; } + public bool IsCurrentGrabWidgetPinned() { return IsUserInteractingWithAnyWidget() && m_CurrentGrabWidget.Pinned; } + public bool CanCurrentGrabWidgetBePinned() { return IsUserInteractingWithAnyWidget() && m_CurrentGrabWidget.AllowPinning; } + public bool DidUserGrabWithBothInside() { return m_GrabBrush.startedGrabInsideWidget && m_GrabWand.startedGrabInsideWidget; } + public bool IsUserGrabbingWidget(GrabWidget widget) { return widget == m_CurrentGrabWidget; } + public bool IsUserTwoHandGrabbingWidget() { return m_GrabWidgetState == GrabWidgetState.TwoHands; } + public bool IsPinCushionShowing() { return m_PinCushion.IsShowing(); } + public bool IsUserLookingAtPanel(BasePanel panel) + { + return m_CurrentGazeObject > -1 && + m_PanelManager.GetAllPanels()[m_CurrentGazeObject].m_Panel == panel; + } + + public SaveIconTool GetSaveIconTool() + { + return m_SaveIconTool; + } + + public DropCamWidget GetDropCampWidget() + { + return m_DropCam; + } + + public bool IsGrabWorldStateStable() + { + return m_GrabWorldState == GrabWorldState.Normal; + } + + // Internal: modify Coords.ScenePose or Coords.CanvasPose depending on the + // state of m_InTransformCanvasMode + TrTransform GrabbedPose + { + get + { + return App.Scene.Pose; + } + set + { + App.Scene.Pose = value; + } + } + + public Transform GazeObjectTransform() + { + if (m_CurrentGazeObject != -1) + { + return m_PanelManager.GetPanel(m_CurrentGazeObject).transform; + } + return null; + } + + public void ForceShowUIReticle(bool bVisible) + { + m_UIReticle.SetActive(bVisible); + } + + public void SetUIReticleTransform(Vector3 vPos, Vector3 vForward) + { + m_UIReticle.transform.position = vPos; + m_UIReticle.transform.forward = vForward; + } + + public bool AtlasIconTextures + { + get { return m_AtlasIconTextures; } + } + + public IconTextureAtlas IconTextureAtlas + { + get { return GetComponent(); } + } + public GrabWidget CurrentGrabWidget => m_CurrentGrabWidget; + + void DismissPopupOnCurrentGazeObject(bool force) + { + if (m_CurrentGazeObject != -1) + { + m_PanelManager.GetPanel(m_CurrentGazeObject).CloseActivePopUp(force); + } + } + + void Awake() + { + m_Instance = this; + + BrushController.m_Instance.BrushSetToDefault += OnBrushSetToDefault; + + IconTextureAtlas.Init(); + + m_MultiCamCaptureRig = GetComponentInChildren(true); + m_MultiCamCaptureRig.Init(); + + m_CameraPathCaptureRig = GetComponentInChildren(true); + m_CameraPathCaptureRig.Init(); + + m_SketchSurfacePanel = m_SketchSurface.GetComponent(); + m_PanelManager = GetComponent(); + m_PanelManager.Init(); + InitGazePanels(); + + m_WidgetManager = GetComponent(); + m_WidgetManager.Init(); + + m_InputStateConfigs = new InputStateConfig[(int)InputState.Num]; + for (int i = 0; i < (int)InputState.Num; ++i) + { + m_InputStateConfigs[i] = new InputStateConfig(); + m_InputStateConfigs[i].m_AllowDrawing = false; + m_InputStateConfigs[i].m_AllowMovement = true; + m_InputStateConfigs[i].m_ShowGizmo = false; + } + + m_InputStateConfigs[(int)InputState.Standard].m_AllowDrawing = true; + m_InputStateConfigs[(int)InputState.Pan].m_AllowDrawing = true; + m_InputStateConfigs[(int)InputState.HeadLock].m_AllowDrawing = true; + m_InputStateConfigs[(int)InputState.ControllerLock].m_AllowDrawing = true; + m_InputStateConfigs[(int)InputState.PushPull].m_AllowDrawing = true; + + m_InputStateConfigs[(int)InputState.Pan].m_AllowMovement = false; + m_InputStateConfigs[(int)InputState.Rotation].m_AllowMovement = false; + m_InputStateConfigs[(int)InputState.ControllerLock].m_AllowMovement = false; + m_InputStateConfigs[(int)InputState.PushPull].m_AllowMovement = false; + m_InputStateConfigs[(int)InputState.BrushSize].m_AllowMovement = false; + + m_InputStateConfigs[(int)InputState.Pan].m_ShowGizmo = true; + m_InputStateConfigs[(int)InputState.Rotation].m_ShowGizmo = true; + m_InputStateConfigs[(int)InputState.HeadLock].m_ShowGizmo = true; + m_InputStateConfigs[(int)InputState.PushPull].m_ShowGizmo = true; + + m_CurrentGazeRay = new Ray(Vector3.zero, Vector3.forward); + m_GazeControllerRay = new Ray(Vector3.zero, Vector3.forward); + m_GazeControllerRayActivePanel = new Ray(Vector3.zero, Vector3.forward); + + m_GrabWidgetHoldHistory = new Queue(); + m_GrabWidgetOneHandInfo = new GrabWidgetControllerInfo(); + + // Initialize world grip members. + m_GrabBrush.grabTransform = TrTransform.identity; + m_GrabWand.grabTransform = TrTransform.identity; + + m_BrushResults = new Queue(); + m_WandResults = new Queue(); + m_WidgetGpuIntersectionLayer = LayerMask.NameToLayer("GpuIntersection"); + m_CurrentGrabIntersectionState = GrabIntersectionState.RequestIntersections; + } + + public void InitGazePanels() + { + // Find all gaze panels. + int iNumGazePanels = m_PanelManager.GetAllPanels().Count; + m_GazeResults = new GazeResult[iNumGazePanels]; + for (int i = 0; i < iNumGazePanels; ++i) + { + m_GazeResults[i] = new GazeResult(); + m_GazeResults[i].m_HitWithGaze = false; + m_GazeResults[i].m_HitWithController = false; + m_GazeResults[i].m_WithinView = false; + m_GazeResults[i].m_GazePosition = new Vector3(); + } + } + + public void OnEnable() + { + // This needs to run before other tools initialize, which is why it's running in OnEnable. + // The sequence is Awake(), OnEnable(), Start(). + if (App.VrSdk.GetControllerDof() == VrSdk.DoF.Six) + { + SetInFreePaintMode(true); + SetInitialTool(BaseTool.ToolType.FreePaintTool); + } + } + + void Start() + { + m_TransformGizmo = (GameObject)Instantiate(m_TransformGizmoPrefab); + m_TransformGizmo.transform.parent = transform; + m_TransformGizmoScript = m_TransformGizmo.GetComponent(); + m_TransformGizmo.SetActive(false); + + m_RotationIcon = (GameObject)Instantiate(m_RotationIconPrefab); + m_RotationIcon.transform.position = m_SketchSurface.transform.position; + m_RotationIcon.transform.parent = m_SketchSurface.transform; + m_RotationIcon.SetActive(false); + + GameObject pinCushionObj = (GameObject)Instantiate(m_PinCushionPrefab); + m_PinCushion = pinCushionObj.GetComponent(); + + m_PositionOffsetResetTapTime = 0.0f; + + m_UndoHold_Timer = m_UndoRedoHold_DurationBeforeStart; + m_RedoHold_Timer = m_UndoRedoHold_DurationBeforeStart; + + m_AutoOrientAfterRotation = true; + m_RotationCursor.gameObject.SetActive(false); + + ResetGrabbedPose(); + m_SketchOrigin = m_SketchSurface.transform.position; + + m_PanelManager.InitPanels(m_ControlsType == ControlsType.SixDofControllers); + + m_UIReticleMobile.SetActive(m_ControlsType == ControlsType.ViewingOnly); + m_UIReticleSixDofController.SetActive(m_ControlsType != ControlsType.ViewingOnly); + + m_PositioningPanelWithHead = false; + m_PositioningSpeed = 16.0f; + + m_CurrentRotationType = RotationType.All; + m_RotationResetTapTime = 0.0f; + + m_CurrentInputState = InputState.Standard; + + m_SketchSurfacePanel.EnableSpecificTool(m_InitialTool); + m_SurfaceLockControllerBaseScalar = m_SketchSurfacePanel.m_PanelSensitivity; + + //after initializing, start with gaze objects hidden + m_CurrentGazeObject = -1; + m_EatInputGazeObject = false; + + // Previously set to 0 in experimental builds + int hidePanelsDelay = 1; + + StartCoroutine(DelayedHidePanels(hidePanelsDelay)); + + m_DropCam.Show(false); + + m_GrabWidgetState = GrabWidgetState.None; + + UpdateDraftingVisibility(); + + m_DisableWorldGrabbing = false; + } + + private IEnumerator DelayedHidePanels(int frames) + { + int stall = frames; + while (stall-- > 0) + { + yield return null; + } + + m_PanelManager.HidePanelsForStartup(); + RequestPanelsVisibility(false); + } + + void Update() + { + // TODO: we need to figure out what transform to pass in here! + // Maybe best _just for now_ to use the scene transform? + TrTransform scenePose = App.Scene.Pose; + Shader.SetGlobalMatrix("xf_CS", scenePose.ToMatrix4x4()); + Shader.SetGlobalMatrix("xf_I_CS", scenePose.inverse.ToMatrix4x4()); + } + + void LateUpdate() + { + // Gracefully exits if we're not recording a video. + VideoRecorderUtils.SerializerNewUsdFrame(); + } + + public bool IsFreepaintToolReady() + { + return + !m_PinCushion.IsShowing() && + !PointerManager.m_Instance.IsStraightEdgeProxyActive() && + !InputManager.m_Instance.ControllersAreSwapping() && + (m_SketchSurfacePanel.IsSketchSurfaceToolActive() || + (m_SketchSurfacePanel.GetCurrentToolType() == BaseTool.ToolType.FreePaintTool)) + ; + } + + public void UpdateControls() + { + UnityEngine.Profiling.Profiler.BeginSample("SketchControlsScript.UpdateControls"); + m_SketchSurfacePanel.m_UpdatedToolThisFrame = false; + + // Verify controllers are available and prune state if they're not. + if ((App.VrSdk.GetControllerDof() == VrSdk.DoF.Six && + App.VrSdk.IsInitializingUnityXR) && App.VrSdk.IsHmdInitialized()) + { + m_PanelManager.SetVisible(false); + PointerManager.m_Instance.RequestPointerRendering(false); + return; + } + + //mouse movement + Vector2 mv = InputManager.m_Instance.GetMouseMoveDelta(); + m_MouseDeltaX = mv.x; + m_MouseDeltaY = mv.y; + + UpdateGazeObjectsAnimationState(); + UpdateCurrentGazeRay(); + m_SketchSurfacePanel.SetBacksideActive(m_CurrentGazeRay.origin); + m_PanelManager.UpdatePanels(); + + m_MouseDeltaXScaled = m_MouseDeltaX * GetAppropriateMovementScalar(); + m_MouseDeltaYScaled = m_MouseDeltaY * GetAppropriateMovementScalar(); + + //this is used for one-shot inputs that don't require state and do not change state + UpdateBaseInput(); + + UpdatePinCushionVisibility(); + + //if the pointer manager is processing, we don't want to respond to input + if (!PointerManager.m_Instance.IsMainPointerProcessingLine()) + { + + //see if we're grabbing a widget + UpdateGrab(); + + //see if we're looking at a gaze object + RefreshCurrentGazeObject(); + + // Tools allowed when widgets aren't grabbed. + bool bWidgetGrabOK = m_GrabWidgetState == GrabWidgetState.None; + + // If we don't have a widget held and we're not grabbing the world with the brush controller, + // update tools. + if (bWidgetGrabOK && !m_GrabBrush.grabbingWorld) + { + if (m_CurrentGazeObject != -1 && !m_WorldBeingGrabbed) + { + UpdateActiveGazeObject(); + + // Allow for standard input (like Undo / Redo) even when gazing at a panel. + if (m_CurrentInputState == InputState.Standard) + { + UpdateStandardInput(); + } + } + else + { + //standard input, no gaze object + if (m_InputStateConfigs[(int)m_CurrentInputState].m_AllowMovement) + { + m_SketchSurfacePanel.UpdateReticleOffset(m_MouseDeltaX, m_MouseDeltaY); + } + + switch (m_CurrentInputState) + { + case InputState.Standard: + UpdateStandardInput(); + break; + case InputState.Pan: + UpdatePanInput(); + break; + case InputState.Rotation: + UpdateRotationInput(); + break; + case InputState.HeadLock: + UpdateHeadLockInput(); + break; + case InputState.ControllerLock: + UpdateControllerLock(); + break; + case InputState.PushPull: + UpdatePushPullInput(); + break; + case InputState.Save: + UpdateSaveInput(); + break; + case InputState.Load: + UpdateLoadInput(); + break; + } + + //keep pointer locked in the right spot, even if it's hidden + if (m_SketchSurfacePanel.ActiveTool.LockPointerToSketchSurface()) + { + Vector3 vPointerPos = Vector3.zero; + Vector3 vPointerForward = Vector3.zero; + m_SketchSurfacePanel.GetReticleTransform(out vPointerPos, out vPointerForward, + (m_ControlsType == ControlsType.ViewingOnly)); + PointerManager.m_Instance.SetMainPointerPosition(vPointerPos); + PointerManager.m_Instance.SetMainPointerForward(vPointerForward); + } + + m_SketchSurfacePanel.AllowDrawing(m_InputStateConfigs[(int)m_CurrentInputState].m_AllowDrawing); + m_SketchSurfacePanel.UpdateCurrentTool(); + + PointerManager.m_Instance.AllowPointerPreviewLine(IsFreepaintToolReady()); + //keep transform gizmo at sketch surface pos + m_TransformGizmo.transform.position = m_SketchSurface.transform.position; + bool bGizmoActive = m_InputStateConfigs[(int)m_CurrentInputState].m_ShowGizmo && m_SketchSurfacePanel.ShouldShowTransformGizmo(); + m_TransformGizmo.SetActive(bGizmoActive); + } + } + } + + // Update any transition to a scene transform reset. + UpdateWorldTransformReset(); + + //update our line after all input and tools have chimed in on the state of it + PointerManager.m_Instance.UpdateLine(); + UnityEngine.Profiling.Profiler.EndSample(); + } + + public void UpdateControlsPostIntro() + { + m_PanelManager.UpdatePanels(); + UpdateCurrentGazeRay(); + UpdateGazeObjectsAnimationState(); + RefreshCurrentGazeObject(); + UpdateSwapControllers(); + if (m_CurrentGazeObject > -1) + { + UpdateActiveGazeObject(); + } + } + + public void UpdateControlsForLoading() + { + UpdateCurrentGazeRay(); + m_PanelManager.UpdatePanels(); + UpdateGazeObjectsAnimationState(); + UpdateGrab(); + UpdateWorldTransformReset(); + + if (m_GrabWidgetState == GrabWidgetState.None && m_CurrentGazeObject == -1 && + m_SketchSurfacePanel.ActiveTool.AvailableDuringLoading() && + !m_GrabBrush.grabbingWorld) + { + m_SketchSurfacePanel.UpdateCurrentTool(); + } + } + + public void UpdateControlsForReset() + { + UpdateGrab(); + UpdateCurrentGazeRay(); + UpdatePinCushionVisibility(); + m_PanelManager.UpdatePanels(); + UpdateGazeObjectsAnimationState(); + PointerManager.m_Instance.UpdateLine(); + } + + public void UpdateControlsForUploading() + { + UpdateCurrentGazeRay(); + UpdatePinCushionVisibility(); + m_PanelManager.UpdatePanels(); + UpdateGazeObjectsAnimationState(); + } + + public void UpdateControlsForMemoryExceeded() + { + UpdateGrab(); + m_SketchSurfacePanel.m_UpdatedToolThisFrame = false; + m_PanelManager.UpdatePanels(); + UpdateCurrentGazeRay(); + UpdateGazeObjectsAnimationState(); + RefreshCurrentGazeObject(); + if (m_CurrentGazeObject > -1) + { + UpdateActiveGazeObject(); + } + } + + void UpdatePinCushionVisibility() + { + // If the pin cushion is showing and the user cancels, eat the input. + // if (m_PinCushion.IsShowing()) + // { + // if (InputManager.m_Instance.GetCommand(InputManager.SketchCommands.Activate) || + // InputManager.Brush.GetControllerGrip() || + // InputManager.Wand.GetControllerGrip() || + // IsUserInteractingWithAnyWidget() || + // IsUserInteractingWithUI()) + // { + // m_EatPinCushionInput = true; + // } + // } + + // If our tool wants the input blocked, maintain the input eat state until + // after the user has let off input. + if (m_SketchSurfacePanel.ActiveTool.BlockPinCushion() || !CanUsePinCushion()) + { + m_EatPinCushionInput = true; + } + + bool show = + InputManager.m_Instance.GetCommand(InputManager.SketchCommands.ShowPinCushion); + m_PinCushion.ShowPinCushion(show && !m_EatPinCushionInput); + m_EatPinCushionInput = m_EatPinCushionInput && show; + } + + bool CanUsePinCushion() + { + return (m_ControlsType == ControlsType.SixDofControllers) && + m_PanelManager.AdvancedModeActive() && + !InputManager.m_Instance.GetCommand(InputManager.SketchCommands.Activate) && + !InputManager.Brush.GetControllerGrip() && + !InputManager.Wand.GetControllerGrip() && + !IsUserInteractingWithAnyWidget() && + !IsUserInteractingWithUI() && + !m_SketchSurfacePanel.ActiveTool.BlockPinCushion() && + App.Instance.IsInStateThatAllowsPainting(); + } + + void UpdateCurrentGazeRay() + { + var head = ViewpointScript.Head; + m_CurrentGazeRay = new Ray(head.position, head.forward); + m_CurrentHeadOrientation = head.rotation; + + // We use the gaze ray for certain shader effects - like edge falloff. + Shader.SetGlobalVector("_WorldSpaceRootCameraPosition", m_CurrentGazeRay.origin); + bool hasController = m_ControlsType == ControlsType.SixDofControllers; + if (hasController) + { + if (InputManager.Brush.IsTrackedObjectValid) + { + Transform rAttachPoint = InputManager.m_Instance.GetBrushControllerAttachPoint(); + m_GazeControllerRay.direction = rAttachPoint.forward; + m_GazeControllerRay.origin = rAttachPoint.position; + } + else + { + // If the brush controller isn't tracked, put our controller ray out of the way. + float fBig = 9999999.0f; + m_GazeControllerRay.direction = Vector3.one; + m_GazeControllerRay.origin = new Vector3(fBig, fBig, fBig); + } + + m_GazeControllerRayActivePanel.direction = m_GazeControllerRay.direction; + m_GazeControllerRayActivePanel.origin = m_GazeControllerRay.origin; + m_GazeControllerRayActivePanel.origin -= (m_GazeControllerRayActivePanel.direction * 0.5f); + } + } + + public void UpdateGazeObjectsAnimationState() + { + // Are the panels allowed to be visible? + bool isSixDof = m_ControlsType == ControlsType.SixDofControllers; + if ((!isSixDof) || + (InputManager.Wand.IsTrackedObjectValid && + !m_SketchSurfacePanel.ActiveTool.HidePanels() && + !App.Instance.IsLoading())) + { + // Transition panels according to requested visibility. + m_PanelManager.SetVisible(m_PanelsVisibilityRequested); + } + else + { + // Transition out. + m_PanelManager.SetVisible(false); + } + } + + void UpdateBaseInput() + { + UnityEngine.Profiling.Profiler.BeginSample("SketchControlScript.UpdateBaseInput"); + if (m_ControlsType == ControlsType.SixDofControllers) + { + m_PanelManager.UpdateWandOrientationControls(); + } + + //allow tool scaling if we're not drawing and our input device is active + bool bScaleInputActive = InputManager.m_Instance.GetCommand(InputManager.SketchCommands.Scale); + bool bScaleCommandActive = + bScaleInputActive + && !InputManager.m_Instance.GetCommand(InputManager.SketchCommands.Activate) + && m_GrabBrush.grabbingWorld == false + && m_CurrentGazeObject == -1 // free up swipe for use by gaze object + && (m_ControlsType != ControlsType.SixDofControllers || InputManager.Brush.IsTrackedObjectValid) + // TODO:Mikesky - very hacky + && SketchSurfacePanel.m_Instance.ActiveTool.m_Type != BaseTool.ToolType.MultiCamTool; + + if (m_EatToolScaleInput) + { + m_EatToolScaleInput = bScaleInputActive; + } + + if (bScaleCommandActive && !m_EatToolScaleInput) + { + if (m_GrabWidgetState == GrabWidgetState.None) + { + //send scale command down to current tool + m_SketchSurfacePanel.UpdateToolSize( + m_AdjustToolSizeScalar * InputManager.m_Instance.GetAdjustedBrushScrollAmount()); + } + + //ugly, but brush size is becoming not an input state + m_MouseDeltaX = 0.0f; + m_MouseDeltaY = 0.0f; + } + + UpdateSwapControllers(); + UnityEngine.Profiling.Profiler.EndSample(); + } + + void UpdateSwapControllers() + { + // Don't allow controller swap in first run intro. + // Don't allow controller swap if we're grabbing a widget. + // Don't allow controller swap if a Logitech pen is present. + if (!TutorialManager.m_Instance.TutorialActive() && + m_GrabWidgetState == GrabWidgetState.None && + !App.VrSdk.VrControls.LogitechPenIsPresent()) + { + if (InputManager.m_Instance.GetCommandDown(InputManager.SketchCommands.SwapControls)) + { + DoSwapControls(); + } + } + } + + public static void DoSwapControls() + { + InputManager.m_Instance.WandOnRight = !InputManager.m_Instance.WandOnRight; + InputManager.m_Instance.GetControllerBehavior(InputManager.ControllerName.Brush) + .DisplayControllerSwapAnimation(); + InputManager.m_Instance.GetControllerBehavior(InputManager.ControllerName.Wand) + .DisplayControllerSwapAnimation(); + AudioManager.m_Instance.PlayControllerSwapSound( + InputManager.m_Instance.GetControllerPosition(InputManager.ControllerName.Brush)); + } + + void UpdateStandardInput() + { + UnityEngine.Profiling.Profiler.BeginSample("SketchControlScript.UpdateStandardInput"); + //debug keys + if (App.UserConfig.Flags.AdvancedKeyboardShortcuts) + { + var camTool = SketchSurfacePanel.m_Instance.ActiveTool as MultiCamTool; + + if (InputManager.m_Instance.GetKeyboardShortcutDown(InputManager.KeyboardShortcut.SaveNew)) + { + IssueGlobalCommand(GlobalCommands.SaveNew, 1); + } + else if (InputManager.m_Instance.GetKeyboardShortcutDown( + InputManager.KeyboardShortcut.SwitchCamera) && camTool != null) + { + camTool.ExternalObjectNextCameraStyle(); // For monoscopic mode + } + else if (InputManager.m_Instance.GetKeyboardShortcutDown( + InputManager.KeyboardShortcut.ViewOnly)) + { + IssueGlobalCommand(GlobalCommands.ViewOnly); + } + else if (InputManager.m_Instance.GetKeyboardShortcutDown( + InputManager.KeyboardShortcut.ToggleScreenMirroring)) + { + ViewpointScript.m_Instance.ToggleScreenMirroring(); + } + else if (InputManager.m_Instance.GetKeyboardShortcutDown( + InputManager.KeyboardShortcut.PreviousTool)) + { + m_SketchSurfacePanel.PreviousTool(); + } + else if (InputManager.m_Instance.GetKeyboardShortcutDown( + InputManager.KeyboardShortcut.NextTool)) + { + m_SketchSurfacePanel.NextTool(); + } + else if (InputManager.m_Instance.GetKeyboardShortcutDown( + InputManager.KeyboardShortcut.CycleSymmetryMode)) + { + var cur = PointerManager.m_Instance.CurrentSymmetryMode; + var next = (cur == SymmetryMode.None) ? SymmetryMode.SinglePlane + : (cur == SymmetryMode.SinglePlane) ? SymmetryMode.DebugMultiple + : (cur == SymmetryMode.DebugMultiple) ? SymmetryMode.MultiMirror + : (cur == SymmetryMode.MultiMirror) ? SymmetryMode.TwoHanded + : SymmetryMode.None; + PointerManager.m_Instance.CurrentSymmetryMode = next; + } + else if (InputManager.m_Instance.GetKeyboardShortcutDown( + InputManager.KeyboardShortcut.Export)) + { + StartCoroutine(ExportCoroutine()); + } + else if (InputManager.m_Instance.GetKeyboardShortcutDown( + InputManager.KeyboardShortcut.StoreHeadTransform) && + InputManager.m_Instance.GetAnyShift()) + { + Transform head = ViewpointScript.Head; + PlayerPrefs.SetFloat("HeadOffset_localPositionX", head.localPosition.x); + PlayerPrefs.SetFloat("HeadOffset_localPositionY", head.localPosition.y); + PlayerPrefs.SetFloat("HeadOffset_localPositionZ", head.localPosition.z); + PlayerPrefs.SetFloat("HeadOffset_localRotationX", head.localRotation.x); + PlayerPrefs.SetFloat("HeadOffset_localRotationY", head.localRotation.y); + PlayerPrefs.SetFloat("HeadOffset_localRotationZ", head.localRotation.z); + PlayerPrefs.SetFloat("HeadOffset_localRotationW", head.localRotation.w); + } + else if (InputManager.m_Instance.GetKeyboardShortcutDown( + InputManager.KeyboardShortcut.RecallHeadTransform)) + { + Transform head = ViewpointScript.Head; + // Toggle the head offset. + if (m_HeadOffset) + { + // Remove the offset. + Transform originalParent = head.parent; + head.SetParent(head.parent.parent); + GameObject.DestroyImmediate(originalParent.gameObject); + m_HeadOffset = false; + } + else + { + // Add the offset. + GameObject newParent = new GameObject(); + newParent.transform.SetParent(head.parent); + newParent.transform.localPosition = Vector3.zero; + newParent.transform.localRotation = Quaternion.identity; + newParent.transform.localScale = Vector3.one; + head.SetParent(newParent.transform); + TrTransform offsetTransform = TrTransform.TR( + new Vector3( + PlayerPrefs.GetFloat("HeadOffset_localPositionX", 0), + PlayerPrefs.GetFloat("HeadOffset_localPositionY", 1.5f), + PlayerPrefs.GetFloat("HeadOffset_localPositionZ", 0)), + new Quaternion( + PlayerPrefs.GetFloat("HeadOffset_localRotationX", 0), + PlayerPrefs.GetFloat("HeadOffset_localRotationY", 0), + PlayerPrefs.GetFloat("HeadOffset_localRotationZ", 0), + PlayerPrefs.GetFloat("HeadOffset_localRotationW", 1))); + TrTransform originalTransformInverse = TrTransform.FromLocalTransform(head).inverse; + TrTransform newParentTransform = offsetTransform * originalTransformInverse; + newParent.transform.localPosition = newParentTransform.translation; + newParent.transform.localRotation = newParentTransform.rotation; + m_HeadOffset = true; + } + } + else if (InputManager.m_Instance.GetKeyboardShortcutDown( + InputManager.KeyboardShortcut.ToggleLightType)) + { + // Toggle between per-pixel & SH lighting on the secondary directional light + Light secondaryLight = App.Scene.GetLight((1)); + if (LightRenderMode.ForceVertex == secondaryLight.renderMode) + { + secondaryLight.renderMode = LightRenderMode.ForcePixel; + } + else + { + secondaryLight.renderMode = LightRenderMode.ForceVertex; + } + } + else if (InputManager.m_Instance.GetKeyboardShortcutDown( + InputManager.KeyboardShortcut.TossWidget)) + { + m_WidgetManager.TossNearestWidget(); + } + else if (InputManager.m_Instance.GetKeyboardShortcutDown( + InputManager.KeyboardShortcut.Reset)) + { + App.Instance.SetDesiredState(App.AppState.LoadingBrushesAndLighting); + } + else if (InputManager.m_Instance.GetKeyboardShortcutDown( + InputManager.KeyboardShortcut.FlyMode)) + { + SketchSurfacePanel.m_Instance.EnableSpecificTool(BaseTool.ToolType.FlyTool); + } + else if (App.Config.m_ToggleProfileOnAppButton && + (InputManager.Wand.GetVrInputDown(VrInput.Button03) || + InputManager.m_Instance.GetKeyboardShortcutDown( + InputManager.KeyboardShortcut.ToggleProfile))) + { + IssueGlobalCommand(GlobalCommands.ToggleProfiling); + } + } + +#if DEBUG + if (InputManager.m_Instance.GetKeyboardShortcutDown( + InputManager.KeyboardShortcut.CheckStrokes)) + { + bool value = !SketchMemoryScript.m_Instance.m_SanityCheckStrokes; + string feature = "Stroke determinism checking"; + SketchMemoryScript.m_Instance.m_SanityCheckStrokes = value; + OutputWindowScript.m_Instance.CreateInfoCardAtController( + InputManager.ControllerName.Brush, + feature + (value ? ": On" : ": Off")); + } +#endif + + bool hasController = m_ControlsType == ControlsType.SixDofControllers; + var mouse = Mouse.current; + + // Toggle default tool. + if (!m_PanelManager.AdvancedModeActive() && + InputManager.m_Instance.GetCommandDown(InputManager.SketchCommands.ToggleDefaultTool) && + !m_SketchSurfacePanel.IsDefaultToolEnabled() && + m_SketchSurfacePanel.ActiveTool.AllowDefaultToolToggle() && + // don't allow tool to change while pointing at panel because there is no visual indication + m_CurrentGazeObject == -1) + { + m_SketchSurfacePanel.EnableDefaultTool(); + AudioManager.m_Instance.PlayPinCushionSound(true); + } + // Pan. + else if (!hasController && mouse.rightButton.isPressed) + { + SwitchState(InputState.Pan); + } + // Controller lock (this must be before rotate/head lock!). + else if (!hasController && + InputManager.m_Instance.GetCommand(InputManager.SketchCommands.LockToController)) + { + SwitchState(InputState.ControllerLock); + } + // Rotate. + else if (!hasController && + InputManager.m_Instance.GetCommand(InputManager.SketchCommands.PivotRotation)) + { + SwitchState(InputState.Rotation); + } + // Head lock. + else if (!hasController && + InputManager.m_Instance.GetCommand(InputManager.SketchCommands.LockToHead)) + { + SwitchState(InputState.HeadLock); + } + // Push pull. + else if (!hasController && + InputManager.m_Instance.GetCommand(InputManager.SketchCommands.AltActivate)) + { + SwitchState(InputState.PushPull); + } + else if (!PointerManager.m_Instance.IsMainPointerCreatingStroke()) + { + // Reset surface. + if (!hasController && + InputManager.m_Instance.GetCommandDown(InputManager.SketchCommands.Reset)) + { + ResetGrabbedPose(); + } + // Undo. + else if (InputManager.m_Instance.GetCommandDown(InputManager.SketchCommands.Undo) && + CanUndo()) + { + IssueGlobalCommand(GlobalCommands.Undo); + } + else if (InputManager.m_Instance.GetCommand(InputManager.SketchCommands.Undo) && + CanUndo() && ShouldRepeatUndo()) + { + m_UndoHold_Timer = m_UndoRedoHold_RepeatInterval; + IssueGlobalCommand(GlobalCommands.Undo); + } + // Redo. + else if (InputManager.m_Instance.GetCommandDown(InputManager.SketchCommands.Redo) && + CanRedo()) + { + IssueGlobalCommand(GlobalCommands.Redo); + } + else if (InputManager.m_Instance.GetCommand(InputManager.SketchCommands.Redo) && + CanRedo() && ShouldRepeatRedo()) + { + m_RedoHold_Timer = m_UndoRedoHold_RepeatInterval; + IssueGlobalCommand(GlobalCommands.Redo); + } + // Reset scene. + else if (!hasController && + InputManager.m_Instance.GetKeyboardShortcutDown( + InputManager.KeyboardShortcut.ResetScene)) + { + // TODO: Should thsi go away? Seems like the "sweetspot" may no longer be used. + if (App.VrSdk.GetControllerDof() == VrSdk.DoF.Two) + { + m_PanelManager.SetSweetSpotPosition(m_CurrentGazeRay.origin); + ResetGrabbedPose(); + } + } + // Straight edge. + else if (!hasController && + InputManager.m_Instance.GetKeyboardShortcutDown( + InputManager.KeyboardShortcut.StraightEdge)) + { + IssueGlobalCommand(GlobalCommands.StraightEdge); + } + // Always fall back on switching tools. + else + { + m_SketchSurfacePanel.CheckForToolSelection(); + } + } + + // Reset undo/redo hold timers. + if (!InputManager.m_Instance.GetCommand(InputManager.SketchCommands.Undo)) + { + m_UndoHold_Timer = m_UndoRedoHold_DurationBeforeStart; + } + if (!InputManager.m_Instance.GetCommand(InputManager.SketchCommands.Redo)) + { + m_RedoHold_Timer = m_UndoRedoHold_DurationBeforeStart; + } + UnityEngine.Profiling.Profiler.EndSample(); + } + + bool CanUndo() + { + return SketchMemoryScript.m_Instance.CanUndo() && + !IsUIBlockingUndoRedo() && + m_PanelManager.GazePanelsAreVisible() && + !m_GrabWand.grabbingWorld && + !InputManager.m_Instance.GetCommand(InputManager.SketchCommands.Activate) && + !SelectionManager.m_Instance.IsAnimatingTossFromGrabbingGroup; + } + + bool CanRedo() + { + return SketchMemoryScript.m_Instance.CanRedo() && + !IsUIBlockingUndoRedo() && + m_PanelManager.GazePanelsAreVisible() && + !m_GrabBrush.grabbingWorld && + !InputManager.m_Instance.GetCommand(InputManager.SketchCommands.Activate) && + !SelectionManager.m_Instance.IsAnimatingTossFromGrabbingGroup; + } + + bool ShouldRepeatUndo() + { + m_UndoHold_Timer -= Time.deltaTime; + return (m_UndoHold_Timer <= 0.0f); + } + + bool ShouldRepeatRedo() + { + m_RedoHold_Timer -= Time.deltaTime; + return (m_RedoHold_Timer <= 0.0f); + } + + // Updates the global state: + // m_CurrentGrabWidget + void UpdateGrab() + { + UnityEngine.Profiling.Profiler.BeginSample("SketchControlScript.UpdateGrab"); + if (m_ControlsType != ControlsType.SixDofControllers) + { + UnityEngine.Profiling.Profiler.EndSample(); + return; + } + + GrabWidget rPrevGrabWidget = m_CurrentGrabWidget; + GrabWidget rPrevPotentialBrush = m_PotentialGrabWidgetBrush; + GrabWidget rPrevPotentialWand = m_PotentialGrabWidgetWand; + if (m_CurrentGrabWidget) + { + m_CurrentGrabWidget.Activate(false); + } + if (m_PotentialGrabWidgetBrush) + { + m_PotentialGrabWidgetBrush.Activate(false); + } + if (m_PotentialGrabWidgetWand) + { + m_PotentialGrabWidgetWand.Activate(false); + } + m_CurrentGrabWidget = null; + m_PotentialGrabWidgetBrush = null; + m_PotentialGrabWidgetWand = null; + m_PotentialGrabWidgetBrushValid = false; + m_PotentialGrabWidgetWandValid = false; + + m_WidgetManager.RefreshNearestWidgetLists(m_CurrentGazeRay, m_CurrentGazeObject); + + if (m_GrabWidgetState == GrabWidgetState.None) + { + UpdateGrab_WasNone(rPrevPotentialBrush, rPrevPotentialWand); + } + else if (m_GrabWidgetState == GrabWidgetState.OneHand) + { + UpdateGrab_WasOneHand(rPrevGrabWidget); + } + else if (m_GrabWidgetState == GrabWidgetState.TwoHands) + { + UpdateGrab_WasTwoHands(rPrevGrabWidget); + } + + // Update grab intersection state. + switch (m_CurrentGrabIntersectionState) + { + case GrabIntersectionState.RequestIntersections: + m_CurrentGrabIntersectionState = GrabIntersectionState.ReadBrush; + break; + case GrabIntersectionState.ReadBrush: + m_CurrentGrabIntersectionState = GrabIntersectionState.ReadWand; + break; + case GrabIntersectionState.ReadWand: + m_CurrentGrabIntersectionState = GrabIntersectionState.RequestIntersections; + break; + } + + if (!TutorialManager.m_Instance.TutorialActive() && m_CurrentGrabWidget == null) + { + UpdateGrab_World(); + } + + App.Instance.SelectionEffect.HighlightForGrab( + m_GrabWidgetState != GrabWidgetState.None || + (m_PotentialGrabWidgetBrush != null && m_PotentialGrabWidgetBrushValid) || + (m_PotentialGrabWidgetWand != null && m_PotentialGrabWidgetWandValid)); + UnityEngine.Profiling.Profiler.EndSample(); + } + + void UpdateGrab_WasNone(GrabWidget rPrevPotentialBrush, GrabWidget rPrevPotentialWand) + { + // if a panel isn't in focus, allow for widget grab + // We can grab a widget as long as we aren't trying to draw with that hand. + bool bActiveInput = + (InputManager.m_Instance.GetCommand(InputManager.SketchCommands.Activate) && + App.Instance.IsInStateThatAllowsPainting()); + + //certain tools don't allow us to mess with widgets + bool bWidgetManipOK = m_SketchSurfacePanel.DoesCurrentToolAllowWidgetManipulation() && + !m_GrabWand.grabbingWorld && !m_GrabBrush.grabbingWorld && IsGrabWorldStateStable() && + App.Instance.IsInStateThatAllowsAnyGrabbing(); + + // Update EatInput flags if they're valid. + if (m_GrabBrush.eatInput) + { + m_GrabBrush.eatInput = InputManager.Brush.GetControllerGrip(); + } + if (m_GrabWand.eatInput) + { + m_GrabWand.eatInput = InputManager.Wand.GetControllerGrip(); + } + + bool bShouldClearWandInside = false; + if (m_CurrentInputState == InputState.Standard && bWidgetManipOK) + { + // If we're in the intersection request state, fire off a new intersection request. If + // we're in the read brush state, update our brush grab data structure. + List brushBests = m_WidgetManager.WidgetsNearBrush; + if (m_CurrentGrabIntersectionState == GrabIntersectionState.RequestIntersections) + { + RequestWidgetIntersection(brushBests, InputManager.ControllerName.Brush); + } + else if (m_CurrentGrabIntersectionState == GrabIntersectionState.ReadBrush) + { + m_BackupBrushGrabData = GetBestWidget(brushBests, m_BrushResults); + } + + if (m_BackupBrushGrabData != null) + { + m_PotentialGrabWidgetBrush = m_BackupBrushGrabData.m_WidgetScript; + + // Allow widget grab if we're not painting. + if (!bActiveInput) + { + m_PotentialGrabWidgetBrush.Activate(true); + m_PotentialGrabWidgetBrushValid = true; + m_PotentialGrabWidgetBrush.VisualizePinState(); + + if (!m_GrabBrush.eatInput && InputManager.Brush.GetControllerGrip()) + { + m_CurrentGrabWidget = m_PotentialGrabWidgetBrush; + if (m_CurrentGrabWidget.Group != SketchGroupTag.None) + { + m_GrabBrush.grabbingGroup = true; + m_CurrentGrabWidget = + SelectionManager.m_Instance.StartGrabbingGroupWithWidget(m_CurrentGrabWidget); + } + UpdateGrab_NoneToOne(InputManager.ControllerName.Brush); + bShouldClearWandInside = true; + m_GrabBrush.startedGrabInsideWidget = true; + } + } + } + m_GrabBrush.SetHadBestGrabAndTriggerHaptics(m_BackupBrushGrabData); + m_ControllerGrabVisuals.BrushInWidgetRange = m_BackupBrushGrabData != null; + + // If we're in the intersection request state, fire off a new intersection request. If + // we're in the read wand state, update our wand grab data structure. + List wandBests = m_WidgetManager.WidgetsNearWand; + if (m_CurrentGrabIntersectionState == GrabIntersectionState.RequestIntersections) + { + RequestWidgetIntersection(wandBests, InputManager.ControllerName.Wand); + } + else if (m_CurrentGrabIntersectionState == GrabIntersectionState.ReadWand) + { + m_BackupWandGrabData = GetBestWidget(wandBests, m_WandResults); + } + + if (m_BackupWandGrabData != null) + { + m_PotentialGrabWidgetWand = m_BackupWandGrabData.m_WidgetScript; + // Allow wand widget grab if brush grab failed. + bool bGrabAllowed = (m_GrabWidgetState == GrabWidgetState.None) && !bActiveInput; + if (bGrabAllowed) + { + m_PotentialGrabWidgetWand.Activate(true); + m_PotentialGrabWidgetWandValid = true; + m_PotentialGrabWidgetWand.VisualizePinState(); + + if (!m_GrabWand.eatInput && InputManager.Wand.GetControllerGrip()) + { + m_CurrentGrabWidget = m_PotentialGrabWidgetWand; + if (m_CurrentGrabWidget.Group != SketchGroupTag.None) + { + m_GrabWand.grabbingGroup = true; + m_CurrentGrabWidget = + SelectionManager.m_Instance.StartGrabbingGroupWithWidget(m_CurrentGrabWidget); + } + UpdateGrab_NoneToOne(InputManager.ControllerName.Wand); + m_GrabBrush.ClearInsideWidget(); + m_GrabWand.startedGrabInsideWidget = true; + } + } + } + m_GrabWand.SetHadBestGrabAndTriggerHaptics(m_BackupWandGrabData); + m_ControllerGrabVisuals.WandInWidgetRange = m_BackupWandGrabData != null; + + // Account for asymmetry in controller processing by clearing after wand has updated + // GrabState.insideWidget according to bestWandGrab. + if (bShouldClearWandInside) + { + m_GrabWand.ClearInsideWidget(); + } + } + + // Update widget collisions if we've got a drifter. + if (m_GrabWidgetState == GrabWidgetState.None) + { + if (m_WidgetManager.ShouldUpdateCollisions()) + { + m_PanelManager.DoCollisionSimulationForWidgetPanels(); + } + } + } + + void UpdateGrab_WasOneHand(GrabWidget rPrevGrabWidget) + { + var controller = InputManager.Controllers[(int)m_GrabWidgetOneHandInfo.m_Name]; + bool shouldRelease = !App.Instance.IsInStateThatAllowsAnyGrabbing(); + if (!InputManager.Controllers[(int)m_GrabWidgetOneHandInfo.m_Name].GetControllerGrip() || + shouldRelease) + { + if (shouldRelease) + { + EatGrabInput(); + } + + Vector3 vLinearVelocity; + Vector3 vAngularVelocity; + if (GetGrabWidgetHoldHistory(out vLinearVelocity, out vAngularVelocity)) + { + rPrevGrabWidget.SetVelocities( + vLinearVelocity, vAngularVelocity, + controller.Transform.position); + } + // One -> None + UpdateGrab_ToNone(rPrevGrabWidget); + } + else + { + // Keep holding on to our widget. + m_CurrentGrabWidget = rPrevGrabWidget; + m_CurrentGrabWidget.Activate(true); + m_CurrentGrabWidget.UserInteracting(true, m_GrabWidgetOneHandInfo.m_Name); + + if (!m_CurrentGrabWidget.Pinned) + { + var info = InputManager.Controllers[(int)m_GrabWidgetOneHandInfo.m_Name]; + var controllerXf = Coords.AsGlobal[info.Transform]; + var newWidgetXf = controllerXf * m_GrabWidgetOneHandInfo.m_BaseWidgetXf_LS; + m_CurrentGrabWidget.RecordAndSetPosRot(newWidgetXf); + + UpdateGrabWidgetHoldHistory(m_GrabWidgetOneHandInfo.m_Name); + } + + m_PanelManager.DoCollisionSimulationForWidgetPanels(); + + // Check for widget pinning. + if (m_CurrentGrabWidget.AllowPinning) + { + if (InputManager.Controllers[(int)m_GrabWidgetOneHandInfo.m_Name].GetCommandDown( + InputManager.SketchCommands.PinWidget)) + { + // If the user initiates a pin action, buzz a bit. + if (!m_CurrentGrabWidget.Pinned) + { + InputManager.m_Instance.TriggerHapticsPulse( + m_GrabWidgetOneHandInfo.m_Name, 3, 0.10f, 0.07f); + } + m_CurrentGrabWidget.Pin(!m_CurrentGrabWidget.Pinned); + SketchSurfacePanel.m_Instance.EatToolsInput(); + m_WidgetManager.RefreshPinAndUnpinLists(); + } + } + + if (m_CurrentGrabWidget is SelectionWidget) + { + if (InputManager.m_Instance.GetCommandDown( + InputManager.SketchCommands.DuplicateSelection)) + { + controller.LastHeldInput = + controller.GetCommandHoldInput(InputManager.SketchCommands.DuplicateSelection); + } + + if (controller.LastHeldInput != null && + InputManager.m_Instance.GetCommandHeld(InputManager.SketchCommands.DuplicateSelection)) + { + SketchControlsScript.m_Instance.IssueGlobalCommand( + SketchControlsScript.GlobalCommands.Duplicate); + } + } + + InputManager.ControllerName otherName = + (m_GrabWidgetOneHandInfo.m_Name == InputManager.ControllerName.Brush) ? + InputManager.ControllerName.Wand : InputManager.ControllerName.Brush; + bool otherInputEaten = + (m_GrabWidgetOneHandInfo.m_Name == InputManager.ControllerName.Brush) ? + m_GrabWand.eatInput : m_GrabBrush.eatInput; + + // See if the other controller decides to grab the widget (unless we're pinned). + if (!m_CurrentGrabWidget.Pinned) + { + if (m_CurrentGrabWidget.AllowTwoHandGrab) + { + if (InputManager.Controllers[(int)otherName].GetControllerGrip()) + { + RequestPanelsVisibility(false); + m_GrabWidgetState = GrabWidgetState.TwoHands; + // Figure out if the new grab starts inside the widget. + Vector3 vOtherGrabPos = TrTransform.FromTransform( + InputManager.m_Instance.GetController(otherName)).translation; + bool bOtherGrabInBounds = m_CurrentGrabWidget.GetActivationScore( + vOtherGrabPos, otherName) >= 0; + m_CurrentGrabWidget.SetUserTwoHandGrabbing( + true, m_GrabWidgetOneHandInfo.m_Name, otherName, bOtherGrabInBounds); + + if (otherName == InputManager.ControllerName.Brush) + { + m_GrabBrush.startedGrabInsideWidget = bOtherGrabInBounds; + } + else + { + m_GrabWand.startedGrabInsideWidget = bOtherGrabInBounds; + } + + m_GrabWidgetTwoHandBrushPrev = TrTransform.FromTransform( + InputManager.m_Instance.GetController(InputManager.ControllerName.Brush)); + m_GrabWidgetTwoHandWandPrev = TrTransform.FromTransform( + InputManager.m_Instance.GetController(InputManager.ControllerName.Wand)); + } + } + } + else if (!otherInputEaten && InputManager.Controllers[(int)otherName].GetControllerGrip()) + { + // If it's a two hand grab but the current grab widget is pinned, grab the world. + UpdateGrab_ToNone(m_CurrentGrabWidget); + m_CurrentGrabWidget = null; + m_ControllerGrabVisuals.SetDesiredVisualState(ControllerGrabVisuals.VisualState.Off); + } + } + } + + // Previous frame was a two-handed grab. + // Handles all the cases where this frame's grab is zero, one, or two hands. + void UpdateGrab_WasTwoHands(GrabWidget rPrevGrabWidget) + { + //keep holding on to our widget + m_CurrentGrabWidget = rPrevGrabWidget; + m_CurrentGrabWidget.Activate(true); + m_CurrentGrabWidget.UserInteracting(true, m_GrabWidgetOneHandInfo.m_Name); + + if (!App.Instance.IsInStateThatAllowsAnyGrabbing()) + { + m_CurrentGrabWidget.SetUserTwoHandGrabbing(false); + UpdateGrab_ToNone(rPrevGrabWidget); + } + else if (!InputManager.Wand.GetControllerGrip()) + { // Look for button release. + m_CurrentGrabWidget.SetUserTwoHandGrabbing(false); + // See if our Brush hand is still within grab range of the widget. + if (m_GrabBrush.startedGrabInsideWidget || + IsControllerNearWidget(InputManager.ControllerName.Brush, m_CurrentGrabWidget)) + { + m_GrabWidgetOneHandInfo.m_Name = InputManager.ControllerName.Brush; + RequestPanelsVisibility(true); + InitializeGrabWidgetControllerInfo(m_GrabWidgetOneHandInfo); + m_GrabWidgetState = GrabWidgetState.OneHand; + } + else + { + // If the Brush hand is beyond the widget, we're not holding it anymore. + UpdateGrab_ToNone(rPrevGrabWidget); + + // Eat input on the brush grip until we release the button. + m_GrabBrush.eatInput = true; + } + } + else if (!InputManager.Brush.GetControllerGrip()) + { + m_CurrentGrabWidget.SetUserTwoHandGrabbing(false); + if (m_GrabWand.startedGrabInsideWidget || + IsControllerNearWidget(InputManager.ControllerName.Wand, m_CurrentGrabWidget)) + { + m_GrabWidgetOneHandInfo.m_Name = InputManager.ControllerName.Wand; + InitializeGrabWidgetControllerInfo(m_GrabWidgetOneHandInfo); + m_GrabWidgetState = GrabWidgetState.OneHand; + } + else + { + UpdateGrab_ToNone(rPrevGrabWidget); + m_GrabWand.eatInput = true; + } + } + else + { + // Both hands still grabbing. + // Check for pin, which forcibly releases one of the hands. + if (m_CurrentGrabWidget.AllowPinning && + InputManager.Controllers[(int)m_GrabWidgetOneHandInfo.m_Name].GetCommandDown( + InputManager.SketchCommands.PinWidget)) + { + // If the user initiates a pin action, buzz a bit. + if (!m_CurrentGrabWidget.Pinned) + { + InputManager.m_Instance.TriggerHapticsPulse( + m_GrabWidgetOneHandInfo.m_Name, 3, 0.10f, 0.07f); + } + + m_CurrentGrabWidget.Pin(!m_CurrentGrabWidget.Pinned); + SketchSurfacePanel.m_Instance.EatToolsInput(); + m_WidgetManager.RefreshPinAndUnpinLists(); + + InitializeGrabWidgetControllerInfo(m_GrabWidgetOneHandInfo); + m_GrabWidgetState = GrabWidgetState.OneHand; + m_CurrentGrabWidget.SetUserTwoHandGrabbing(false); + + // Eat input on the off hand so we don't immediately jump in to world transform. + if (m_GrabWidgetOneHandInfo.m_Name == InputManager.ControllerName.Brush) + { + RequestPanelsVisibility(true); + m_GrabWand.eatInput = true; + } + else + { + m_GrabBrush.eatInput = true; + } + } + + if (!m_CurrentGrabWidget.Pinned) + { + UpdateGrab_ContinuesTwoHands(); + } + } + ClearGrabWidgetHoldHistory(); + m_PanelManager.DoCollisionSimulationForWidgetPanels(); + } + + // Common case for two-handed grab: both the previous and current frames are two-handed. + private void UpdateGrab_ContinuesTwoHands() + { + //holding with two hands, transform accordingly + TrTransform xfBrush = TrTransform.FromTransform(InputManager.Brush.Transform); + TrTransform xfWand = TrTransform.FromTransform(InputManager.Wand.Transform); + Vector2 vSizeRange = m_CurrentGrabWidget.GetWidgetSizeRange(); + + GrabWidget.Axis axis = m_CurrentGrabWidget.GetScaleAxis( + xfWand.translation, xfBrush.translation, + out Vector3 axisDirection, out float axisExtent); + + TrTransform newWidgetXf; + if (axis != GrabWidget.Axis.Invalid) + { + // Scale along a single axis + float deltaScale; + if (App.Config.m_AxisManipulationIsResize) + { + newWidgetXf = MathUtils.TwoPointObjectTransformationAxisResize( + axisDirection, axisExtent, + m_GrabWidgetTwoHandWandPrev, m_GrabWidgetTwoHandBrushPrev, + xfWand, xfBrush, + GetWorkingTransform(m_CurrentGrabWidget), + out deltaScale, + deltaScaleMin: vSizeRange.x / axisExtent, + deltaScaleMax: vSizeRange.y / axisExtent); + } + else + { + newWidgetXf = MathUtils.TwoPointObjectTransformationNonUniformScale( + axisDirection, + m_GrabWidgetTwoHandWandPrev, m_GrabWidgetTwoHandBrushPrev, + xfWand, xfBrush, + GetWorkingTransform(m_CurrentGrabWidget), + out deltaScale, + finalScaleMin: vSizeRange.x, + deltaScaleMin: vSizeRange.x / axisExtent, + deltaScaleMax: vSizeRange.y / axisExtent); + } + + // The above functions return undefined values in newWidgetXf.scale; but that's + // okay because RecordAndSetPosRot ignores xf.scale. + // TODO: do this more cleanly + m_CurrentGrabWidget.RecordAndApplyScaleToAxis(deltaScale, axis); + } + else + { + // Uniform scaling + TrTransform xfObject = GetWorkingTransform(m_CurrentGrabWidget); + Vector3 extents = (m_CurrentGrabWidget is StencilWidget) + ? (m_CurrentGrabWidget as StencilWidget).Extents + : Vector3.one * Mathf.Abs(m_CurrentGrabWidget.GetSignedWidgetSize()); + + // Delta-scale bounds should be based on the smallest/largest extent. + // Irritatingly, the API wants absolute rather than relative scale bounds, + // so they need even more conversion. + float deltaScaleMin = vSizeRange.x / extents.Min(); + float deltaScaleMax = vSizeRange.y / extents.Max(); + if (m_GrabWand.startedGrabInsideWidget && m_GrabBrush.startedGrabInsideWidget) + { + newWidgetXf = MathUtils.TwoPointObjectTransformation( + m_GrabWidgetTwoHandWandPrev, m_GrabWidgetTwoHandBrushPrev, + xfWand, xfBrush, + xfObject, + deltaScaleMin: deltaScaleMin, deltaScaleMax: deltaScaleMax); + } + else if (m_GrabWand.startedGrabInsideWidget) + { + // keep the wand inside the object + newWidgetXf = MathUtils.TwoPointObjectTransformation( + m_GrabWidgetTwoHandWandPrev, m_GrabWidgetTwoHandBrushPrev, + xfWand, xfBrush, + xfObject, + deltaScaleMin: deltaScaleMin, deltaScaleMax: deltaScaleMax, + bUseLeftAsPivot: true); + } + else + { + // keep the brush inside the object (note the brush is the left hand) + newWidgetXf = MathUtils.TwoPointObjectTransformation( + m_GrabWidgetTwoHandBrushPrev, m_GrabWidgetTwoHandWandPrev, + xfBrush, xfWand, + xfObject, + deltaScaleMin: deltaScaleMin, deltaScaleMax: deltaScaleMax, + bUseLeftAsPivot: true); + } + + // Must do separately becvause RecordAndSetPosRot ignores newWidgetXf.scale + m_CurrentGrabWidget.RecordAndSetSize(newWidgetXf.scale); + + float currentSize = Mathf.Abs(m_CurrentGrabWidget.GetSignedWidgetSize()); + if (currentSize == vSizeRange.x || currentSize == vSizeRange.y) + { + InputManager.m_Instance.TriggerHaptics(InputManager.ControllerName.Brush, 0.05f); + InputManager.m_Instance.TriggerHaptics(InputManager.ControllerName.Wand, 0.05f); + } + } + + // Ignores TrTransform.scale + m_CurrentGrabWidget.RecordAndSetPosRot(newWidgetXf); + + m_GrabWidgetTwoHandBrushPrev = xfBrush; + m_GrabWidgetTwoHandWandPrev = xfWand; + } + + void UpdateGrab_NoneToOne(InputManager.ControllerName controllerName) + { + if (m_MaybeDriftingGrabWidget != null && + m_MaybeDriftingGrabWidget.IsMoving() && + !m_MaybeDriftingGrabWidget.IsSpinningFreely) + { + // If a new widget is grabbed but the previous one is still drifting, end the drift. + // TODO: Simplify in the widget animation cleanup. + if (m_MaybeDriftingGrabWidget == m_CurrentGrabWidget) + { + SketchMemoryScript.m_Instance.PerformAndRecordCommand( + new MoveWidgetCommand(m_MaybeDriftingGrabWidget, + m_MaybeDriftingGrabWidget.LocalTransform, m_MaybeDriftingGrabWidget.CustomDimension, + final: true), + discardIfNotMerged: true); + } + m_MaybeDriftingGrabWidget.ClearVelocities(); + } + + // UserInteracting should be the first thing that happens here so OnUserBeginInteracting can + // be called before everything else. + m_CurrentGrabWidget.UserInteracting(true, controllerName); + m_CurrentGrabWidget.ClearVelocities(); + ClearGrabWidgetHoldHistory(); + + //set our info names according to this controller's name + m_GrabWidgetOneHandInfo.m_Name = controllerName; + InitializeGrabWidgetControllerInfo(m_GrabWidgetOneHandInfo); + + PointerManager.m_Instance.AllowPointerPreviewLine(false); + PointerManager.m_Instance.RequestPointerRendering(false); + m_SketchSurfacePanel.RequestHideActiveTool(true); + if (m_GrabWidgetOneHandInfo.m_Name == InputManager.ControllerName.Wand) + { + RequestPanelsVisibility(false); + } + + // Notify visuals. + ControllerGrabVisuals.VisualState visualState = + m_GrabWidgetOneHandInfo.m_Name == InputManager.ControllerName.Brush ? + ControllerGrabVisuals.VisualState.WidgetBrushGrip : + ControllerGrabVisuals.VisualState.WidgetWandGrip; + m_ControllerGrabVisuals.SetDesiredVisualState(visualState); + m_ControllerGrabVisuals.SetHeldWidget(m_CurrentGrabWidget.transform); + + //if a gaze object had focus when we grabbed this widget, take focus off the object + ResetActivePanel(); + m_UIReticle.SetActive(false); + + // Prep all other grab widgets for collision. + m_PanelManager.PrimeCollisionSimForWidgets(m_CurrentGrabWidget); + + m_GrabWidgetState = GrabWidgetState.OneHand; + m_WidgetManager.WidgetsDormant = false; + PointerManager.m_Instance.EatLineEnabledInput(); + + m_BackupWandGrabData = null; + m_BackupBrushGrabData = null; + } + + void UpdateGrab_ToNone(GrabWidget rPrevGrabWidget) + { + m_MaybeDriftingGrabWidget = rPrevGrabWidget; + + m_GrabWidgetState = GrabWidgetState.None; + PointerManager.m_Instance.RequestPointerRendering(!App.Instance.IsLoading() && + m_SketchSurfacePanel.ShouldShowPointer()); + RequestPanelsVisibility(true); + m_SketchSurfacePanel.RequestHideActiveTool(false); + rPrevGrabWidget.UserInteracting(false); + + // Disable grab visuals. + m_ControllerGrabVisuals.SetDesiredVisualState(ControllerGrabVisuals.VisualState.Off); + m_ControllerGrabVisuals.SetHeldWidget(null); + + if (m_GrabBrush.grabbingGroup || m_GrabWand.grabbingGroup) + { + SelectionManager.m_Instance.EndGrabbingGroupWithWidget(); + m_GrabBrush.grabbingGroup = false; + m_GrabWand.grabbingGroup = false; + } + } + + void RequestWidgetIntersection(List candidates, + InputManager.ControllerName controllerName) + { + // Get locals based off what controller we're using. + Queue resultQueue = null; + Vector3 controllerPos = Vector3.zero; + if (controllerName == InputManager.ControllerName.Brush) + { + resultQueue = m_BrushResults; + controllerPos = InputManager.m_Instance.GetBrushControllerAttachPoint().position; + } + else + { + resultQueue = m_WandResults; + controllerPos = InputManager.m_Instance.GetWandControllerAttachPoint().position; + } + + // If we don't have a candidate that has a GPU object, don't bother firing off a GPU request. + bool requestGpuIntersection = false; + + // Fire off a new GPU intersection with all widgets that can use it. + for (int i = 0; i < candidates.Count; ++i) + { + if (candidates[i].m_WidgetScript.HasGPUIntersectionObject()) + { + candidates[i].m_WidgetScript.SetGPUIntersectionObjectLayer(m_WidgetGpuIntersectionLayer); + requestGpuIntersection = true; + } + } + + if (requestGpuIntersection) + { + GpuIntersectionResult newRequest = new GpuIntersectionResult(); + newRequest.resultList = new List(); + newRequest.result = App.Instance.GpuIntersector.RequestModelIntersections( + controllerPos, m_WidgetGpuIntersectionRadius, newRequest.resultList, 8, + (1 << m_WidgetGpuIntersectionLayer)); + + // The new result will only be null when the intersector is disabled. + if (newRequest.result != null) + { + resultQueue.Enqueue(newRequest); + } + + for (int i = 0; i < candidates.Count; ++i) + { + if (candidates[i].m_WidgetScript.HasGPUIntersectionObject()) + { + candidates[i].m_WidgetScript.RestoreGPUIntersectionObjectLayer(); + } + } + } + } + + GrabWidgetData GetBestWidget(List candidates, + Queue resultQueue) + { + // Discard futures that are too old. + while (resultQueue.Count > 0) + { + if (Time.frameCount - resultQueue.Peek().result.StartFrame < 5) + { + break; + } + resultQueue.Dequeue(); + } + + // If the oldest future is ready, use its intersection result to update the candidates. + GpuIntersectionResult finishedResult; + if (resultQueue.Count > 0 && resultQueue.Peek().result.IsReady) + { + finishedResult = resultQueue.Dequeue(); + } + else + { + finishedResult.resultList = new List(); + } + + // TODO: Speed this up. + for (int i = 0; i < candidates.Count; ++i) + { + if (candidates[i].m_WidgetScript.HasGPUIntersectionObject()) + { + // If a candidate can't find itself in the finished results list, it's not eligible. + bool candidateValid = false; + for (int j = 0; j < finishedResult.resultList.Count; ++j) + { + if (candidates[i].m_WidgetScript.Equals(finishedResult.resultList[j].widget)) + { + candidateValid = true; + break; + } + } + + if (candidateValid) + { + // If a candidate has a GPU intersection object and we found it in this list, + // not only is it valid, but it's as valid as it can be. + candidates[i].m_ControllerScore = 1.0f; + } + else + { + candidates[i].m_NearController = false; + } + } + } + + // Run through the candidates and pick + GrabWidgetData best = null; + for (int i = 0; i < candidates.Count; ++i) + { + var candidate = candidates[i]; + if (!candidate.m_NearController) continue; + + // For media widgets - only select from the active layer + if (candidate.m_WidgetScript is MediaWidget + && candidate.m_WidgetScript.Canvas != App.Scene.ActiveCanvas) continue; + + if (best == null || candidate.m_ControllerScore > best.m_ControllerScore) + { + best = candidate; + } + } + return best; + } + + void InitializeGrabWidgetControllerInfo(GrabWidgetControllerInfo info) + { + Transform controller = InputManager.Controllers[(int)info.m_Name].Transform; + Transform widget = m_CurrentGrabWidget.GrabTransform_GS; + TrTransform newWidgetXf = Coords.AsGlobal[widget]; + + info.m_BaseControllerXf = Coords.AsGlobal[controller]; + info.m_BaseWidgetXf_LS = info.m_BaseControllerXf.inverse * newWidgetXf; + } + + // returns the transform of the true widget (not the snapped one for those that can be) + private TrTransform GetWorkingTransform(GrabWidget w) + { + TrTransform ret = w.GetGrabbedTrTransform(); + ret.scale = w.GetSignedWidgetSize(); + return ret; + } + + // Initiate the world transform reset animation. + public void RequestWorldTransformReset(bool toSavedXf = false) + { + if (WorldIsReset(toSavedXf)) + { + return; + } + + m_WorldTransformResetXf = + toSavedXf ? SketchMemoryScript.m_Instance.InitialSketchTransform : TrTransform.identity; + m_WorldTransformResetState = WorldTransformResetState.Requested; + + App.Scene.disableTiltProtection = false; + } + + void UpdateWorldTransformReset() + { + switch (m_WorldTransformResetState) + { + case WorldTransformResetState.Requested: + ViewpointScript.m_Instance.FadeToColor(Color.black, m_GrabWorldFadeSpeed); + m_WorldTransformResetState = WorldTransformResetState.FadingToBlack; + m_xfDropCamReset_RS = Coords.AsRoom[m_DropCam.transform]; + PointerManager.m_Instance.EatLineEnabledInput(); + PointerManager.m_Instance.AllowPointerPreviewLine(false); + break; + case WorldTransformResetState.FadingToBlack: + m_WorldTransformFadeAmount += m_GrabWorldFadeSpeed * Time.deltaTime; + if (m_WorldTransformFadeAmount >= 1.0f) + { + App.Scene.Pose = m_WorldTransformResetXf; + m_WorldTransformFadeAmount = 1.0f; + m_WorldTransformResetState = WorldTransformResetState.FadingToScene; + ViewpointScript.m_Instance.FadeToScene(m_GrabWorldFadeSpeed); + m_DropCam.transform.position = m_xfDropCamReset_RS.translation; + m_DropCam.transform.rotation = m_xfDropCamReset_RS.rotation; + PointerManager.m_Instance.AllowPointerPreviewLine(true); + } + break; + case WorldTransformResetState.FadingToScene: + m_WorldTransformFadeAmount -= m_GrabWorldFadeSpeed * Time.deltaTime; + if (m_WorldTransformFadeAmount <= 0.0f) + { + m_WorldTransformFadeAmount = 0.0f; + m_WorldTransformResetState = WorldTransformResetState.Default; + } + break; + } + } + + bool CheckToggleTiltProtection() + { + if ( + InputManager.Wand.GetCommandDown(InputManager.SketchCommands.Redo) || + InputManager.Brush.GetCommandDown(InputManager.SketchCommands.Redo) + ) + { + App.Scene.disableTiltProtection = !App.Scene.disableTiltProtection; + + return !App.Scene.disableTiltProtection; + } + + return false; + + } + + void UpdateGrab_World() + { + bool bAllowWorldTransform = m_SketchSurfacePanel.ActiveTool.AllowWorldTransformation() && + (m_GrabWorldState != GrabWorldState.ResetDone) && + (!PointerManager.m_Instance.IsMainPointerCreatingStroke() || App.Instance.IsLoading()) && + App.Instance.IsInStateThatAllowsAnyGrabbing() && + !m_DisableWorldGrabbing; + + bool bWorldGrabWandPrev = m_GrabWand.grabbingWorld; + bool bWorldGrabBrushPrev = m_GrabBrush.grabbingWorld; + m_GrabWand.grabbingWorld = bAllowWorldTransform && !m_GrabWand.eatInput && + InputManager.Wand.GetControllerGrip(); + m_GrabBrush.grabbingWorld = bAllowWorldTransform && !m_GrabBrush.eatInput && + InputManager.Brush.GetControllerGrip() && + (m_CurrentGazeObject == -1); + + bool grabsChanged = (bWorldGrabWandPrev != m_GrabWand.grabbingWorld) || + (bWorldGrabBrushPrev != m_GrabBrush.grabbingWorld); + bool bAllowWorldTransformChanged = + bAllowWorldTransform != m_AllowWorldTransformLastFrame; + int nGrabs = m_GrabWand.grabbingWorld ? 1 : 0; + nGrabs += m_GrabBrush.grabbingWorld ? 1 : 0; + + // Allow grabbing again if grabs have changed and we're done resetting. + if (m_GrabWorldState == GrabWorldState.ResetDone && grabsChanged) + { + m_GrabWorldState = GrabWorldState.Normal; + } + + // Update panels visibility if brush grip has changed. + if (bWorldGrabWandPrev != m_GrabWand.grabbingWorld) + { + RequestPanelsVisibility(!m_GrabWand.grabbingWorld); + } + + // Update tool visibility if brush grip has changed. + if (bWorldGrabBrushPrev != m_GrabBrush.grabbingWorld) + { + m_SketchSurfacePanel.RequestHideActiveTool(m_GrabBrush.grabbingWorld); + PointerManager.m_Instance.AllowPointerPreviewLine(!m_GrabBrush.grabbingWorld); + PointerManager.m_Instance.RequestPointerRendering(!m_GrabBrush.grabbingWorld + && m_SketchSurfacePanel.ShouldShowPointer() && !App.Instance.IsLoading()); + } + + // Reset m_WorldBeingGrabbed and only set it when world is actually being grabbed. + bool bWorldBeingGrabbedPrev = m_WorldBeingGrabbed; + m_WorldBeingGrabbed = false; + + // Move the world if it has been grabbed. + if (m_GrabWorldState == GrabWorldState.Normal && bAllowWorldTransform) + { + if (nGrabs == 2) + { + // Two-handed world movement. + m_WorldBeingGrabbed = true; + TrTransform grabXfWand = TrTransform.FromTransform( + InputManager.m_Instance.GetController(InputManager.ControllerName.Wand)); + TrTransform grabXfBrush = TrTransform.FromTransform( + InputManager.m_Instance.GetController(InputManager.ControllerName.Brush)); + + // Offset the controller positions so that they're centered on the grips. + Vector3 gripPos = InputManager.Controllers[(int)InputManager.ControllerName.Brush].Geometry.GripAttachPoint.localPosition; + gripPos.x = 0.0f; + grabXfWand.translation += grabXfWand.MultiplyVector(gripPos); + grabXfBrush.translation += grabXfBrush.MultiplyVector(gripPos); + + // Are we initiating two hand transform this frame? + if (!bWorldGrabWandPrev || !bWorldGrabBrushPrev) + { + PointerManager.m_Instance.EnableLine(false); + PointerManager.m_Instance.AllowPointerPreviewLine(false); + PointerManager.m_Instance.RequestPointerRendering(false); + // Initiate audio loop + m_WorldTransformSpeedSmoothed = 0.0f; + AudioManager.m_Instance.WorldGrabLoop(true); + } + else + { + TrTransform xfOld = GrabbedPose; + TrTransform xfNew; + float deltaScaleMin = WorldTransformMinScale / xfOld.scale; + float deltaScaleMax = WorldTransformMaxScale / xfOld.scale; + bool fixOffset = false; + fixOffset = CheckToggleTiltProtection(); + xfNew = MathUtils.TwoPointObjectTransformation( + m_GrabBrush.grabTransform, m_GrabWand.grabTransform, + grabXfBrush, grabXfWand, + xfOld, + rotationAxisConstraint: (App.Scene.disableTiltProtection ? default(Vector3) : Vector3.up), + deltaScaleMin: deltaScaleMin, deltaScaleMax: deltaScaleMax); + float fCurrentWorldTransformSpeed = + Mathf.Abs((xfNew.scale - xfOld.scale) / Time.deltaTime); + m_WorldTransformSpeedSmoothed = + Mathf.Lerp(m_WorldTransformSpeedSmoothed, fCurrentWorldTransformSpeed, + AudioManager.m_Instance.m_WorldGrabLoopSmoothSpeed * Time.deltaTime); + AudioManager.m_Instance.ChangeLoopVolume("WorldGrab", + Mathf.Clamp(m_WorldTransformSpeedSmoothed / + AudioManager.m_Instance.m_WorldGrabLoopAttenuation, 0f, + AudioManager.m_Instance.m_WorldGrabLoopMaxVolume)); + + if (fixOffset) + { + Vector3 midPoint = Vector3.Lerp(grabXfBrush.translation, grabXfWand.translation, 0.5f); + + Vector3 localMidPointOldXF = xfOld.inverse * midPoint; + + // assign this to force the axial protection + GrabbedPose = xfNew; + xfNew = GrabbedPose; + + Vector3 midPointXFNew = xfNew * localMidPointOldXF; + + TrTransform xfDelta1 = TrTransform.T(midPoint - midPointXFNew); + xfNew = xfDelta1 * xfNew; + } + GrabbedPose = xfNew; + } + + // Update last states. + m_GrabBrush.grabTransform = grabXfBrush; + m_GrabWand.grabTransform = grabXfWand; + } + } + else if (m_GrabWorldState == GrabWorldState.ResettingTransform) + { + if (m_WorldTransformResetState == WorldTransformResetState.FadingToScene) + { + ResetGrabbedPose(); + PanelManager.m_Instance.ExecuteOnPanel(x => x.OnPanelMoved()); + + // World can't be transformed right after a reset until grab states have changed. + if (bAllowWorldTransform) + { + bAllowWorldTransform = false; + bAllowWorldTransformChanged = + bAllowWorldTransform != m_AllowWorldTransformLastFrame; + } + + // Set the grab world state on exit. + if (nGrabs == 0) + { + m_GrabWorldState = GrabWorldState.Normal; + } + else + { + m_GrabWorldState = GrabWorldState.ResetDone; + } + } + } + + if (grabsChanged || bAllowWorldTransformChanged) + { + // Fade in grid when doing two handed spin. + if (nGrabs == 2 && !bAllowWorldTransformChanged) + { + ViewpointScript.m_Instance.FadeGroundPlaneIn(m_GrabWorldGridColor, m_GrabWorldFadeSpeed); + } + else + { + ViewpointScript.m_Instance.FadeGroundPlaneOut(m_GrabWorldFadeSpeed); + } + } + + // Update visuals for world transform + if (grabsChanged) + { + bool bDoubleGrip = m_GrabBrush.grabbingWorld && m_GrabWand.grabbingWorld; + bool bSingleGrip = m_GrabBrush.grabbingWorld || m_GrabWand.grabbingWorld; + Vector3 vControllersMidpoint = + (InputManager.m_Instance.GetControllerPosition(InputManager.ControllerName.Brush) + + InputManager.m_Instance.GetControllerPosition(InputManager.ControllerName.Wand)) * 0.5f; + + // Update transform line visuals + if (bDoubleGrip) + { + m_ControllerGrabVisuals.SetDesiredVisualState(ControllerGrabVisuals.VisualState.WorldDoubleGrip); + AudioManager.m_Instance.WorldGrabbed(vControllersMidpoint); + } + else if (bSingleGrip) + { + if (m_GrabWand.grabbingWorld) + { + m_ControllerGrabVisuals.SetDesiredVisualState(ControllerGrabVisuals.VisualState.WorldWandGrip); + } + else + { + m_ControllerGrabVisuals.SetDesiredVisualState(ControllerGrabVisuals.VisualState.WorldBrushGrip); + } + + if (!bWorldGrabWandPrev && !bWorldGrabBrushPrev) + { + AudioManager.m_Instance.WorldGrabbed(vControllersMidpoint); + } + else + { + AudioManager.m_Instance.WorldGrabLoop(false); + } + } + else + { + m_ControllerGrabVisuals.SetDesiredVisualState(ControllerGrabVisuals.VisualState.Off); + AudioManager.m_Instance.WorldGrabLoop(false); + } + + if (m_GrabWand.grabbingWorld || m_GrabBrush.grabbingWorld) + { + m_WidgetManager.WidgetsDormant = false; + PointerManager.m_Instance.EatLineEnabledInput(); + } + } + + // Reset scene transform if we're gripping and press the track pad. + bool wandReset = m_GrabWand.grabbingWorld && + InputManager.Wand.GetCommandDown(InputManager.SketchCommands.WorldTransformReset); + bool brushReset = m_GrabBrush.grabbingWorld && + InputManager.Brush.GetCommandDown(InputManager.SketchCommands.WorldTransformReset); + if ((wandReset || brushReset) && !WorldIsReset(toSavedXf: false)) + { + m_GrabBrush.eatInput = true; + m_GrabWand.eatInput = true; + m_EatToolScaleInput = true; + m_GrabWorldState = GrabWorldState.ResettingTransform; + RequestWorldTransformReset(); + AudioManager.m_Instance.PlayTransformResetSound(); + } + + // Update the skybox rotation with the new scene rotation. + if (RenderSettings.skybox) + { + Quaternion sceneQuaternion = App.Instance.m_SceneTransform.rotation; + RenderSettings.skybox.SetVector( + "_SkyboxRotation", + new Vector4(sceneQuaternion.x, sceneQuaternion.y, sceneQuaternion.z, sceneQuaternion.w)); + } + + // Update last frame members. + m_AllowWorldTransformLastFrame = bAllowWorldTransform; + } + + /// If lhs and rhs are overlapping, return the smallest vector that would + /// cause rhs to stop overlapping; otherwise, return 0. + /// lhs: an antisphere (solid outside, empty inside) + /// rhs: a sphere (empty outside, solid inside) + private static Vector3 GetOverlap_Antisphere_Sphere( + Vector3 lhsCenter, float lhsRadius, + Vector3 rhsCenter, float rhsRadius) + { + // If anyone passes negative values, they are a bad person + lhsRadius = Mathf.Abs(lhsRadius); + rhsRadius = Mathf.Abs(rhsRadius); + // Without loss of generality, can recenter on lhs + rhsCenter -= lhsCenter; + lhsCenter -= lhsCenter; + + float maxDistance = lhsRadius - rhsRadius; + + // Edge case: sphere does not fit in antisphere + if (maxDistance <= 0) + { + return -rhsCenter; + } + + float penetrationDistance = Mathf.Max(0, rhsCenter.magnitude - maxDistance); + return -penetrationDistance * rhsCenter.normalized; + } + + public static bool IsValidScenePose(TrTransform xf, float radialBounds) + { + // Simple and dumb implementation for now. + return xf == MakeValidScenePose(xf, radialBounds); + } + + /// This is like MakeValidScenePose, but it guarantees that: + /// - The return value is a valid result of Lerp(scene0, scene1, t), + /// for some handwavy definition of "lerp" + /// - The lerp "t" is in [0, 1] + /// - IsValidScenePose(return value) is true, subject to the previous constraints. + /// + /// Think of it as doing a cast from scene0 to scene1. + public static TrTransform MakeValidSceneMove( + TrTransform scene0, TrTransform scene1, float radialBounds) + { + if (IsValidScenePose(scene1, radialBounds)) + { + return scene1; + } + if (!IsValidScenePose(scene0, radialBounds)) + { + Debug.LogError("Invalid scene cast start"); + return scene0; + } + + // We don't support lerping either of these + Debug.Assert(scene0.rotation == scene1.rotation); + Debug.Assert(scene0.scale == scene1.scale); + + Vector3 vRoom0 = -scene0.translation; + Vector3 vRoom1 = -scene1.translation; + float radius = (scene0.scale + * radialBounds + * App.METERS_TO_UNITS) - App.Instance.RoomRadius; + + float t0, t1; + bool success = MathUtils.RaySphereIntersection( + vRoom0, vRoom1 - vRoom0, + Vector3.zero, radius, out t0, out t1); + if (!success) + { + // If this were more important, we could solve for the t of the closest approach + return scene0; + } + + // t0 is expected to be < 0 (room starts inside the fence) + // t1 is expected to be in [0, 1] (room ends outside the fence) + + // Constraints: + // - Lerp t must be in [0, 1]. (Do not move past the requested endpoint) + // - Lerp t should be as high as possible but < t1. (Do not exit the sphere) + float t = Mathf.Clamp(t1, 0, 1); + + TrTransform sceneT = TrTransform.TRS( + Vector3.Lerp(scene0.translation, scene1.translation, t), + scene0.rotation, + scene0.scale); + return MakeValidScenePose(sceneT, radialBounds); + } + + /// Returns a new ScenePose TrTransform that does not cause the room + /// to violate the hard scene bounds. + /// + /// scenePose - The current, possibly invalid scene pose + public static TrTransform MakeValidScenePose(TrTransform scenePose, float radialBounds) + { + scenePose.scale = Mathf.Clamp( + scenePose.scale, + SketchControlsScript.m_Instance.WorldTransformMinScale, + SketchControlsScript.m_Instance.WorldTransformMaxScale); + + // Anything not explicitly qualified is in room space. + + float roomRadius = App.Instance.RoomRadius; + Vector3 roomCenter = Vector3.zero; + + float fenceRadius = scenePose.scale * radialBounds + * App.METERS_TO_UNITS; + Vector3 fenceCenter = scenePose.translation; + + Vector3 moveRoom = GetOverlap_Antisphere_Sphere( + fenceCenter, fenceRadius, roomCenter, roomRadius); + Vector3 moveFence = -moveRoom; + + scenePose.translation += moveFence; + return scenePose; + } + + /// Clears data used by GetGrabWidgetHoldHistory() + /// Should be called any time m_GrabWidgetOneHandInfo changes + void ClearGrabWidgetHoldHistory() + { + m_GrabWidgetHoldHistory.Clear(); + } + + /// Collects data for use with GetGrabWidgetHoldHistory() + void UpdateGrabWidgetHoldHistory(InputManager.ControllerName name) + { + float t = Time.realtimeSinceStartup; + var info = InputManager.Controllers[(int)name]; + m_GrabWidgetHoldHistory.Enqueue(new GrabWidgetHoldPoint + { + m_Name = name, + m_BirthTime = t, + m_Pos = info.Transform.position, + m_Rot = info.Transform.rotation + }); + + // Trim the fat off our widget history + while (m_GrabWidgetHoldHistory.Count > 0 && + t - m_GrabWidgetHoldHistory.Peek().m_BirthTime >= kControlPointHistoryMaxTime) + { + m_GrabWidgetHoldHistory.Dequeue(); + } + } + + /// Returns possibly-smoothed linear and angular velocities. May fail. + /// Angular velocity is returned as an axial vector whose length() is degrees/second + bool GetGrabWidgetHoldHistory(out Vector3 vLinearVelocity, out Vector3 vAngularVelocity) + { + vLinearVelocity = vAngularVelocity = Vector3.zero; + if (m_GrabWidgetHoldHistory.Count < 2) + { + return false; + } + + // We need pairs of elements, so a simple foreach() won't quite work. + // Maybe using linq .First() and .Skip() would be okay. + using (IEnumerator enumerator = m_GrabWidgetHoldHistory.GetEnumerator()) + { + if (!enumerator.MoveNext()) + { + return false; + } + + // Infinitesimal rotations commute, and scaled-axis-angle rotations commute + // "better" than other rotation formats. + Vector3 totalDeltaTheta = Vector3.zero; + + GrabWidgetHoldPoint first = enumerator.Current; + GrabWidgetHoldPoint prev = first; + GrabWidgetHoldPoint current = first; + while (enumerator.MoveNext()) + { + current = enumerator.Current; + + // For our quaternion, find the difference, convert it to angle/axis, and sum it + // Find delta such that delta * prev = cur + // left-multiply because we want it in world-space. + // multiply vs prev since we want the delta that takes us forward in time + // rather than backward in time. + Quaternion dtheta = current.m_Rot * Quaternion.Inverse(prev.m_Rot); + // Assume the rotation took the shorter path + if (dtheta.w < 0) + { + dtheta.Set(-dtheta.x, -dtheta.y, -dtheta.z, -dtheta.w); + } + + float degrees; + Vector3 axis; + dtheta.ToAngleAxis(out degrees, out axis); + totalDeltaTheta += (axis * degrees); + prev = current; + } + + // Linear velocity calculation doesn't need to look at intermediate points + Vector3 totalDeltaPosition = current.m_Pos - first.m_Pos; + float totalDeltaTime = current.m_BirthTime - first.m_BirthTime; + if (totalDeltaTime == 0) + { + return false; + } + + vLinearVelocity = totalDeltaPosition / totalDeltaTime; + vAngularVelocity = totalDeltaTheta / totalDeltaTime; + return true; + } + } + + bool IsControllerNearWidget(InputManager.ControllerName name, GrabWidget widget) + { + Vector3 vControllerPos = InputManager.m_Instance.GetControllerAttachPointPosition(name); + return widget.GetActivationScore(vControllerPos, name) >= 0.0f; + } + + void RefreshCurrentGazeObject() + { + UnityEngine.Profiling.Profiler.BeginSample("SketchControlScript.RefreshCurrentGazeObject"); + int iPrevGazeObject = m_CurrentGazeObject; + m_CurrentGazeObject = -1; + bool bGazeAllowed = (m_CurrentInputState == InputState.Standard) + && !InputManager.m_Instance.GetCommand(InputManager.SketchCommands.Activate) + && !m_SketchSurfacePanel.ActiveTool.InputBlocked() + && (m_GrabWidgetState == GrabWidgetState.None) + && !m_GrabBrush.grabbingWorld + && !m_PinCushion.IsShowing() + && !PointerManager.MainPointerIsPainting() + ; + + bool bGazeDeactivationOverrideWithInput = false; + List aAllPanels = m_PanelManager.GetAllPanels(); + + bool hasController = m_ControlsType == ControlsType.SixDofControllers; + + //if we're re-positioning a panel, keep it active + if (m_PositioningPanelWithHead) + { + m_CurrentGazeObject = iPrevGazeObject; + } + // Only activate gaze objects if we're in standard input mode, and if we don't have the 'draw' + // button held. + else if ((bGazeAllowed || (iPrevGazeObject != -1))) + { + //reset hit flags + for (int i = 0; i < m_GazeResults.Length; ++i) + { + m_GazeResults[i].m_HitWithGaze = false; + m_GazeResults[i].m_HitWithController = false; + m_GazeResults[i].m_WithinView = false; + } + + // If we're in controller mode, find the nearest colliding widget that might get in our way. + float fNearestWidget = 99999.0f; + if (hasController) + { + fNearestWidget = m_WidgetManager.DistanceToNearestWidget(m_GazeControllerRay); + } + + //check all panels for gaze hit + bool bRequireVisibilityCheck = !hasController || (iPrevGazeObject == -1); + if (m_PanelManager.PanelsAreStable()) + { + RaycastHit rHitInfo; + bool bRayHit = false; + int panelsHit = 0; + for (int i = 0; i < aAllPanels.Count; ++i) + { + // Ignore fixed panels when they are not visible. + if (!m_PanelManager.GazePanelsAreVisible() && aAllPanels[i].m_Panel.m_Fixed) + { + continue; + } + + if (aAllPanels[i].m_Panel.gameObject.activeSelf && aAllPanels[i].m_Panel.IsAvailable()) + { + //make sure this b-snap is in view + Vector3 vToPanel = aAllPanels[i].m_Panel.transform.position - m_CurrentGazeRay.origin; + vToPanel.Normalize(); + if (!bRequireVisibilityCheck || Vector3.Angle(vToPanel, m_CurrentGazeRay.direction) < m_GazeMaxAngleFromFacing) + { + if (hasController) + { + if (aAllPanels[i].m_Panel.HasMeshCollider()) + { + //make sure the angle between the pointer and the panel forward is below our max angle + if (Vector3.Angle(aAllPanels[i].m_Panel.transform.forward, m_GazeControllerRay.direction) < m_GazeMaxAngleFromPointing) + { + //make sure the angle between the user-to-panel and the panel forward is reasonable + if (Vector3.Angle(aAllPanels[i].m_Panel.transform.forward, vToPanel) < m_GazeMaxAngleFacingToForward) + { + m_GazeResults[i].m_WithinView = true; + + bRayHit = false; + bRayHit = aAllPanels[i].m_Panel.RaycastAgainstMeshCollider( + m_GazeControllerRay, out rHitInfo, m_GazeControllerPointingDistance); + + if (bRayHit) + { + //if the ray starts inside the panel, we won't get a good hit point, it'll just be zero + if (rHitInfo.point.sqrMagnitude > 0.1f) + { + if (rHitInfo.distance < fNearestWidget) + { + m_GazeResults[i].m_ControllerDistance = rHitInfo.distance; + m_GazeResults[i].m_ControllerPosition = rHitInfo.point; + m_GazeResults[i].m_HitWithController = true; + panelsHit++; + } + } + } + } + } + } + } + else + { + m_GazeResults[i].m_WithinView = true; + if (aAllPanels[i].m_Panel.GetCollider().Raycast(m_CurrentGazeRay, out rHitInfo, m_GazeMaxDistance)) + { + m_GazeResults[i].m_GazePosition = rHitInfo.point; + m_GazeResults[i].m_HitWithGaze = true; + } + } + } + } + } + + // No panels hit within normal ray distance. + // Check if previous panel still pointed to. + if (panelsHit == 0) + { + if (iPrevGazeObject != -1) + { + // Don't allow any panel to hold focus if it's facing away from the user. + Vector3 vToPanel = aAllPanels[iPrevGazeObject].m_Panel.transform.position - + m_CurrentGazeRay.origin; + vToPanel.Normalize(); + if (Vector3.Angle(aAllPanels[iPrevGazeObject].m_Panel.transform.forward, vToPanel) < + m_GazeMaxAngleFacingToForward) + { + float fDist = m_GazeControllerPointingDistance * 1.5f; + bRayHit = aAllPanels[iPrevGazeObject].m_Panel.RaycastAgainstMeshCollider( + m_GazeControllerRayActivePanel, out rHitInfo, fDist); + if (bRayHit) + { + if (rHitInfo.point.sqrMagnitude > 0.1f) + { + if (rHitInfo.distance < fNearestWidget) + { + m_GazeResults[iPrevGazeObject].m_ControllerDistance = rHitInfo.distance; + m_GazeResults[iPrevGazeObject].m_ControllerPosition = rHitInfo.point; + m_GazeResults[iPrevGazeObject].m_HitWithController = true; + } + } + } + } + } + } + } + + //determine what panel we hit, take the one with the lowest controller distance + float fControllerDist = 999.0f; + int iControllerIndex = -1; + if (hasController) + { + for (int i = 0; i < m_GazeResults.Length; ++i) + { + if (m_GazeResults[i].m_HitWithController) + { + if (m_GazeResults[i].m_ControllerDistance < fControllerDist) + { + iControllerIndex = i; + fControllerDist = m_GazeResults[i].m_ControllerDistance; + } + } + } + } + + //if we found something near our controller, take it + if (iControllerIndex != -1) + { + m_CurrentGazeObject = iControllerIndex; + m_CurrentGazeHitPoint = m_GazeResults[iControllerIndex].m_ControllerPosition; + + // TODO: This should not be hardcoded once multiple pointers are allowed. + m_GazeResults[m_CurrentGazeObject].m_ControllerName = InputManager.ControllerName.Brush; + if (m_GazeResults[m_CurrentGazeObject].m_HitWithGaze) + { + //average with the gaze position if we hit that too + m_CurrentGazeHitPoint += m_GazeResults[m_CurrentGazeObject].m_GazePosition; + m_CurrentGazeHitPoint *= 0.5f; + } + } + else + { + //nothing near the controller, see if we're looking at the previous + if (iPrevGazeObject != -1 && m_GazeResults[iPrevGazeObject].m_HitWithGaze) + { + m_CurrentGazeObject = iPrevGazeObject; + m_CurrentGazeHitPoint = m_GazeResults[m_CurrentGazeObject].m_GazePosition; + } + else + { + //controller and gaze not near panel, pick the first panel we're looking at + for (int i = 0; i < m_GazeResults.Length; ++i) + { + if (m_GazeResults[i].m_HitWithGaze) + { + m_CurrentGazeObject = i; + m_CurrentGazeHitPoint = m_GazeResults[i].m_GazePosition; + break; + } + } + } + } + + //forcing users to look away from gaze panel + if (m_EatInputGazeObject && m_CurrentGazeObject != -1) + { + m_CurrentGazeObject = -1; + } + else if (m_CurrentGazeObject == -1) + { + m_EatInputGazeObject = false; + } + } + + //if we're staring at a panel, keep our countdown fresh + if (m_CurrentGazeObject != -1 || m_ForcePanelActivation) + { + m_GazePanelDectivationCountdown = m_GazePanelDectivationDelay; + } + else + { + if (InputManager.m_Instance.GetCommandDown(InputManager.SketchCommands.Activate)) + { + bGazeDeactivationOverrideWithInput = true; + m_GazePanelDectivationCountdown = 0.0f; + } + else + { + m_GazePanelDectivationCountdown -= Time.deltaTime; + } + if (m_GazePanelDectivationCountdown > 0.0f) + { + m_CurrentGazeObject = iPrevGazeObject; + } + } + + //update our positioning timer + if (m_PositioningPanelWithHead) + { + m_PositioningTimer += m_PositioningSpeed * Time.deltaTime; + m_PositioningTimer = Mathf.Min(m_PositioningTimer, 1.0f); + } + else + { + m_PositioningTimer -= m_PositioningSpeed * Time.deltaTime; + m_PositioningTimer = Mathf.Max(m_PositioningTimer, 0.0f); + } + + //prime objects if we change targets + if (iPrevGazeObject != m_CurrentGazeObject) + { + //if we're switching panels, make sure the pointer doesn't streak + PointerManager.m_Instance.DisablePointerPreviewLine(); + + if (iPrevGazeObject != -1) + { + aAllPanels[iPrevGazeObject].m_Panel.PanelGazeActive(false); + aAllPanels[iPrevGazeObject].m_Panel.SetPositioningPercent(0.0f); + } + if (m_CurrentGazeObject != -1) + { + //make sure our line is disabled + if (m_GazeResults[m_CurrentGazeObject].m_ControllerName == InputManager.ControllerName.Brush) + { + PointerManager.m_Instance.EnableLine(false); + PointerManager.m_Instance.AllowPointerPreviewLine(false); + } + + aAllPanels[m_CurrentGazeObject].m_Panel.PanelGazeActive(true); + aAllPanels[m_CurrentGazeObject].m_Panel.SetPositioningPercent(0.0f); + + if (m_GazeResults[m_CurrentGazeObject].m_ControllerName == InputManager.ControllerName.Brush) + { + m_SketchSurfacePanel.RequestHideActiveTool(true); + } + } + else + { + //if we don't have a panel, we need to enable the pointer according to the current tool + PointerManager.m_Instance.RefreshFreePaintPointerAngle(); + PointerManager.m_Instance.RequestPointerRendering(m_SketchSurfacePanel.ShouldShowPointer()); + m_UIReticle.SetActive(false); + m_SketchSurfacePanel.RequestHideActiveTool(false); + if (!bGazeDeactivationOverrideWithInput) + { + m_SketchSurfacePanel.EatToolsInput(); + } + } + + m_PositioningPanelWithHead = false; + } + UnityEngine.Profiling.Profiler.EndSample(); + } + + void UpdateActiveGazeObject() + { + BasePanel currentPanel = m_PanelManager.GetPanel(m_CurrentGazeObject); + currentPanel.SetPositioningPercent(m_PositioningTimer); + bool hasController = m_ControlsType == ControlsType.SixDofControllers; + // Update positioning behavior. + if (m_PositioningPanelWithHead) + { + if (!InputManager.m_Instance.GetCommand(InputManager.SketchCommands.LockToHead) && + !InputManager.m_Instance.GetCommand(InputManager.SketchCommands.LockToController)) + { + // No more positioning. + m_PositioningPanelWithHead = false; + m_PanelManager.m_SweetSpot.EnableBorderSphere(false, Vector3.zero, 0.0f); + currentPanel.PanelHasStoppedMoving(); + } + else + { + //lock the panel to the sweet spot bounds in the direction the user is looking + Quaternion qDiff = m_CurrentHeadOrientation * Quaternion.Inverse(m_PositioningPanelBaseHeadRotation); + Vector3 vAdjustedOffset = qDiff * m_PositioningPanelOffset; + + Vector3 vNewPos = m_PanelManager.m_SweetSpot.transform.position + vAdjustedOffset; + currentPanel.transform.position = vNewPos; + + vAdjustedOffset.Normalize(); + currentPanel.transform.forward = vAdjustedOffset; + + float fHighlightRadius = currentPanel.m_BorderSphereHighlightRadius; + m_PanelManager.m_SweetSpot.EnableBorderSphere(true, vNewPos, fHighlightRadius * m_PositioningTimer); + + //once we've moved this panel, run the simulation on the other panels to resolve collisions + m_PanelManager.DoCollisionSimulationForKeyboardMouse(currentPanel); + } + } + else + { + // It's possible that, on this frame, before this function was called, active gaze was pulled + // from this panel. In this case, we want to skip updating this frame. + // This happens when a panel has gaze and world grab dismisses all panels, for example. + if (currentPanel.IsActive()) + { + //orient to gaze + if (hasController) + { + currentPanel.UpdatePanel(m_GazeControllerRay.direction, m_CurrentGazeHitPoint); + } + else + { + currentPanel.UpdatePanel(m_CurrentGazeRay.direction, m_CurrentGazeHitPoint); + } + } + + if (!hasController) + { + //lock to head if we're holding a lock button.. + bool bLockToHead = InputManager.m_Instance.GetCommand(InputManager.SketchCommands.LockToHead) || + InputManager.m_Instance.GetCommand(InputManager.SketchCommands.LockToController); + + if (bLockToHead) + { + m_PositioningPanelWithHead = true; + m_PositioningPanelBaseHeadRotation = m_CurrentHeadOrientation; + m_PositioningPanelOffset = currentPanel.transform.position - + m_PanelManager.m_SweetSpot.transform.position; + + currentPanel.ResetPanelFlair(); + + //prime all other panels for movement + m_PanelManager.PrimeCollisionSimForKeyboardMouse(); + } + } + + PointerManager.m_Instance.RequestPointerRendering(false); + currentPanel.UpdateReticleOffset(m_MouseDeltaX, m_MouseDeltaY); + } + + // Keep reticle locked in the right spot. + Vector3 reticlePos = Vector3.zero; + Vector3 reticleForward = Vector3.zero; + if (hasController) + { + currentPanel.GetReticleTransformFromPosDir(m_CurrentGazeHitPoint, + m_GazeControllerRay.direction, out reticlePos, out reticleForward); + } + else + { + currentPanel.GetReticleTransform(out reticlePos, out reticleForward, + (m_ControlsType == ControlsType.ViewingOnly)); + } + + SetUIReticleTransform(reticlePos, -reticleForward); + m_UIReticle.SetActive(GetGazePanelActivationRatio() >= 1.0f); + } + + public void ResetActivePanel() + { + m_PanelManager.ResetPanel(m_CurrentGazeObject); + PointerManager.m_Instance.DisablePointerPreviewLine(); + m_PositioningPanelWithHead = false; + m_CurrentGazeObject = -1; + } + + void UpdatePanInput() + { + if (Mouse.current.rightButton.isPressed) + { + Vector3 vPanDiff = Vector3.zero; + vPanDiff += (Vector3.right * m_MouseDeltaXScaled); + vPanDiff += (Vector3.up * m_MouseDeltaYScaled); + Vector3 vSurfacePos = m_SketchSurface.transform.position; + m_SketchSurface.transform.position = vSurfacePos + vPanDiff; + } + else + { + float fCurrentTime = Time.realtimeSinceStartup; + if (fCurrentTime - m_PositionOffsetResetTapTime < m_DoubleTapWindow) + { + if (m_CurrentGazeObject == -1) + { + ResetGrabbedPose(); + } + } + m_PositionOffsetResetTapTime = fCurrentTime; + + SwitchState(InputState.Standard); + } + } + + void UpdateRotationInput() + { + if (InputManager.m_Instance.GetCommand(InputManager.SketchCommands.PivotRotation)) + { + bool bAltInputActive = InputManager.m_Instance.GetCommand(InputManager.SketchCommands.AltActivate); + bool bRollRotation = m_RotationRollActive || bAltInputActive || m_CurrentRotationType == RotationType.RollOnly; + m_RotationIcon.SetActive(bRollRotation); + if (bRollRotation) + { + m_RotationCursorOffset.x += m_MouseDeltaXScaled; + float fRotationAmount = m_RotationCursorOffset.x * -m_RotationRollScalar; + + Quaternion qOffsetRotation = Quaternion.AngleAxis(fRotationAmount, m_SurfaceForward); + Quaternion qNewRotation = qOffsetRotation * m_RotationOrigin; + m_SketchSurface.transform.rotation = qNewRotation; + + m_RotationRollActive = true; + m_RotationCursor.gameObject.SetActive(false); + } + else + { + //update offset with mouse movement + m_RotationCursorOffset.x += m_MouseDeltaXScaled; + m_RotationCursorOffset.y += m_MouseDeltaYScaled; + + //get offset in model space + Vector3 vSurfaceBounds = m_SketchSurface.transform.localScale * 0.5f; + m_RotationCursorOffset.x = Mathf.Clamp(m_RotationCursorOffset.x, -vSurfaceBounds.x, vSurfaceBounds.x); + m_RotationCursorOffset.y = Mathf.Clamp(m_RotationCursorOffset.y, -vSurfaceBounds.y, vSurfaceBounds.y); + float fCursorOffsetDist = m_RotationCursorOffset.magnitude; + float fMaxCursorOffsetDist = vSurfaceBounds.x; + + //transform offset in to world space + Vector3 vTransformedOffset = m_RotationOrigin * m_RotationCursorOffset; + vTransformedOffset.Normalize(); + + //get world space rotation axis + Vector3 vSketchSurfaceRotationAxis = Vector3.Cross(vTransformedOffset, m_SurfaceForward); + vSketchSurfaceRotationAxis.Normalize(); + + //amount to rotate is determined by offset distance from origin + float fSketchSurfaceRotationAngle = Mathf.Min(fCursorOffsetDist / fMaxCursorOffsetDist, 1.0f); + fSketchSurfaceRotationAngle *= m_RotationMaxAngle; + + //set new surface rotation by combining base rotation with angle/axis rotation + Quaternion qOffsetRotation = Quaternion.AngleAxis(fSketchSurfaceRotationAngle, vSketchSurfaceRotationAxis); + Quaternion qNewRotation = qOffsetRotation * m_RotationOrigin; + m_SketchSurface.transform.rotation = qNewRotation; + + //set position of rotation cursor + Vector3 vNewTransformedOffset = qNewRotation * m_RotationCursorOffset; + m_RotationCursor.transform.position = m_SketchSurface.transform.position + vNewTransformedOffset; + m_RotationCursor.transform.rotation = qNewRotation; + + //set position of guide lines + Vector2 vToCenter = m_RotationCursorOffset; + vToCenter.Normalize(); + float fOffsetAngle = Vector2.Angle(vToCenter, Vector2.up); + m_RotationCursor.PositionCursorLines(m_SketchSurface.transform.position, m_SketchSurface.transform.forward, fOffsetAngle, vSurfaceBounds.x * 2.0f); + } + } + else + { + float fCurrentTime = Time.realtimeSinceStartup; + if (fCurrentTime - m_RotationResetTapTime < m_DoubleTapWindow) + { + //reset drawing surface rotation + m_SketchSurface.transform.rotation = Quaternion.identity; + } + m_RotationResetTapTime = fCurrentTime; + + m_SurfaceForward = m_SketchSurface.transform.forward; + m_SurfaceRight = m_SketchSurface.transform.right; + m_SurfaceUp = m_SketchSurface.transform.up; + + if (!m_RotationRollActive && m_AutoOrientAfterRotation && m_SketchSurfacePanel.IsSketchSurfaceToolActive()) + { + //get possible auto rotations + Quaternion qQuatUp = OrientSketchSurfaceToUp(); + Quaternion qQuatForward = OrientSketchSurfaceToForward(); + + //get the angle between our current and desired auto-rotation + float toUpAngle = Quaternion.Angle(qQuatUp, m_SketchSurface.transform.rotation); + float toForwardAngle = Quaternion.Angle(qQuatForward, m_SketchSurface.transform.rotation); + + //set our new rotation to be whichever autorotation is closeset + Quaternion qNewRotation; + if (Mathf.Abs(toUpAngle) < Mathf.Abs(toForwardAngle)) + { + qNewRotation = qQuatUp; + } + else + { + qNewRotation = qQuatForward; + } + + //update the sketch surface + m_SketchSurface.transform.rotation = qNewRotation; + + m_SurfaceForward = m_SketchSurface.transform.forward; + m_SurfaceRight = m_SketchSurface.transform.right; + m_SurfaceUp = m_SketchSurface.transform.up; + } + + SwitchState(InputState.Standard); + } + } + + void UpdateHeadLockInput() + { + if (InputManager.m_Instance.GetCommand(InputManager.SketchCommands.LockToHead)) + { + //compute new position/orientation of sketch surface + Vector3 vTransformedOffset = m_CurrentHeadOrientation * m_SurfaceLockOffset; + Vector3 vSurfacePos = m_CurrentGazeRay.origin + vTransformedOffset; + + Quaternion qDiff = m_CurrentHeadOrientation * Quaternion.Inverse(m_SurfaceLockBaseHeadRotation); + Quaternion qNewSurfaceRot = qDiff * m_SurfaceLockBaseSurfaceRotation; + + m_SketchSurface.transform.position = vSurfacePos; + m_SketchSurface.transform.rotation = qNewSurfaceRot; + } + else + { + m_SurfaceForward = m_SketchSurface.transform.forward; + m_SurfaceRight = m_SketchSurface.transform.right; + m_SurfaceUp = m_SketchSurface.transform.up; + + SwitchState(InputState.Standard); + } + } + + void UpdateControllerLock() + { + if (InputManager.m_Instance.GetCommand(InputManager.SketchCommands.LockToController)) + { + //compute new position/orientation of sketch surface + Vector3 vControllerDiff = InputManager.m_Instance.GetControllerPosition(m_SurfaceLockActingController) - m_SurfaceLockBaseControllerPosition; + m_SketchSurface.transform.position = m_SurfaceLockBaseSurfacePosition + (vControllerDiff * m_SurfaceLockControllerScalar); + + Quaternion qDiff = InputManager.m_Instance.GetControllerRotation(m_SurfaceLockActingController) * Quaternion.Inverse(m_SurfaceLockBaseControllerRotation); + m_SketchSurface.transform.rotation = qDiff * m_SurfaceLockBaseSurfaceRotation; + } + else + { + m_SurfaceForward = m_SketchSurface.transform.forward; + m_SurfaceRight = m_SketchSurface.transform.right; + m_SurfaceUp = m_SketchSurface.transform.up; + + SwitchState(InputState.Standard); + } + } + + void UpdatePushPullInput() + { + bool bRotationActive = InputManager.m_Instance.GetCommand(InputManager.SketchCommands.PivotRotation); + bool bInputActive = InputManager.m_Instance.GetCommand(InputManager.SketchCommands.Activate); + bool bAltInputActive = InputManager.m_Instance.GetCommand(InputManager.SketchCommands.AltActivate); + + if (bRotationActive && bInputActive) + { + SwitchState(InputState.Rotation); + } + else if (bAltInputActive) + { + Vector3 vPos = m_SketchSurface.transform.position; + float fBigDiff = Mathf.Abs(m_MouseDeltaXScaled) > Mathf.Abs(m_MouseDeltaYScaled) ? -m_MouseDeltaXScaled : m_MouseDeltaYScaled; + vPos += Vector3.forward * fBigDiff; + + m_SketchSurface.transform.position = vPos; + } + else + { + SwitchState(InputState.Standard); + } + } + + void UpdateSaveInput() + { + if (!InputManager.m_Instance.GetKeyboardShortcut(InputManager.KeyboardShortcut.Save)) + { + SwitchState(InputState.Standard); + } + } + + void UpdateLoadInput() + { + if (!InputManager.m_Instance.GetKeyboardShortcut(InputManager.KeyboardShortcut.Load)) + { + SwitchState(InputState.Standard); + } + } + + void OnBrushSetToDefault() + { + BrushDescriptor rDefaultBrush = BrushCatalog.m_Instance.DefaultBrush; + PointerManager.m_Instance.SetBrushForAllPointers(rDefaultBrush); + PointerManager.m_Instance.SetAllPointersBrushSize01(0.5f); + PointerManager.m_Instance.MarkAllBrushSizeUsed(); + } + + public void AssignControllerMaterials(InputManager.ControllerName controller) + { + ControllerGeometry geometry = InputManager.GetControllerGeometry(controller); + + // Start from a clean state + geometry.ResetAll(); + + // If the tutorial is enabled, override all materials. + if (TutorialManager.m_Instance.TutorialActive()) + { + InputManager.m_Instance + .GetControllerTutorial(controller) + ?.AssignControllerMaterials(controller); + return; + } + + // If we're grabbing the world, get the materials from the world transform panel. + if (m_GrabBrush.grabbingWorld && controller == InputManager.ControllerName.Brush) + { + TrTransform scenePose = App.Scene.Pose; + if (scenePose.scale != 1 || scenePose.translation != Vector3.zero + || scenePose.rotation != Quaternion.identity) + { + geometry.ShowWorldTransformReset(); + } + return; + } + else if (m_GrabWand.grabbingWorld && controller == InputManager.ControllerName.Wand) + { + TrTransform scenePose = App.Scene.Pose; + if (scenePose.scale != 1 || scenePose.translation != Vector3.zero + || scenePose.rotation != Quaternion.identity) + { + geometry.ShowWorldTransformReset(); + } + return; + } + + // Not grabbing the world, so see if we're grabbing a widget. + if (m_GrabWidgetState != GrabWidgetState.None) + { + m_CurrentGrabWidget.AssignControllerMaterials(controller); + return; + } + + // See if we're highlighting a widget and if that matters. + if (m_CurrentGrabWidget != null && m_CurrentGrabWidget.HasHoverInteractions()) + { + m_CurrentGrabWidget.AssignHoverControllerMaterials(controller); + return; + } + + // Not grabbing the world or a widget, see if we're interacting with a panel. + if (controller == InputManager.ControllerName.Brush && m_CurrentGazeObject != -1) + { + BasePanel panel = m_PanelManager.GetPanel(m_CurrentGazeObject); + panel.AssignControllerMaterials(controller); + return; + } + + // Defaults. + if (controller == InputManager.ControllerName.Wand) + { + if (App.CurrentState != App.AppState.Standard || m_PanelManager.IntroSketchbookMode) + { + // If app is not in standard mode, the actions represented by subsequent material + // assigments cannot be taken. + return; + } + bool creatingStroke = PointerManager.m_Instance.IsMainPointerCreatingStroke(); + bool allowPainting = App.Instance.IsInStateThatAllowsPainting(); + + InputManager.Wand.Geometry.ShowRotatePanels(); + InputManager.Wand.Geometry.ShowUndoRedo(CanUndo() && !creatingStroke && allowPainting, + CanRedo() && !creatingStroke && allowPainting); + } + + // Show the pin cushion icon on the button if it's available. + if (controller == InputManager.ControllerName.Brush && CanUsePinCushion()) + { + InputManager.Brush.Geometry.ShowPinCushion(); + } + + // Finally, override with tools. + m_SketchSurfacePanel.AssignControllerMaterials(controller); + } + + public float GetControllerPadShaderRatio( + InputManager.ControllerName controller, VrInput input) + { + // If we're interacting with a panel, get touch ratio from the panel. + if (controller == InputManager.ControllerName.Brush && m_CurrentGazeObject != -1) + { + BasePanel panel = m_PanelManager.GetPanel(m_CurrentGazeObject); + return panel.GetControllerPadShaderRatio(controller); + } + return SketchSurfacePanel.m_Instance.GetCurrentToolSizeRatio(controller, input); + } + + void SwitchState(InputState rDesiredState) + { + //exit current state + switch (m_CurrentInputState) + { + case InputState.Pan: + m_TransformGizmoScript.ResetTransform(); + break; + case InputState.PushPull: + m_TransformGizmoScript.ResetTransform(); + break; + case InputState.Rotation: + m_RotationRollActive = false; + m_RotationIcon.SetActive(false); + m_RotationCursor.gameObject.SetActive(false); + break; + } + + bool bSketchSurfaceToolActive = m_SketchSurfacePanel.IsSketchSurfaceToolActive(); + + //enter new state + switch (rDesiredState) + { + case InputState.Pan: + m_TransformGizmoScript.SetTransformForPan(); + break; + case InputState.PushPull: + m_TransformGizmoScript.SetTransformForPushPull(); + break; + case InputState.Rotation: + if (bSketchSurfaceToolActive) + { + m_SketchSurface.transform.position = PointerManager.m_Instance.MainPointer.transform.position; + m_SketchSurfacePanel.ResetReticleOffset(); + } + m_RotationOrigin = m_SketchSurface.transform.rotation; + m_RotationCursorOffset = Vector2.zero; + m_RotationCursor.transform.position = m_SketchSurface.transform.position; + m_RotationCursor.transform.rotation = m_SketchSurface.transform.rotation; + m_RotationCursor.ClearCursorLines(m_SketchSurface.transform.position); + m_RotationCursor.gameObject.SetActive(bSketchSurfaceToolActive); + break; + case InputState.HeadLock: + m_SurfaceLockBaseHeadRotation = m_CurrentHeadOrientation; + m_SurfaceLockBaseSurfaceRotation = m_SketchSurface.transform.rotation; + m_SurfaceLockOffset = m_SketchSurface.transform.position - m_CurrentGazeRay.origin; + m_SurfaceLockOffset = Quaternion.Inverse(m_SurfaceLockBaseHeadRotation) * m_SurfaceLockOffset; + break; + case InputState.ControllerLock: + if (bSketchSurfaceToolActive) + { + m_SketchSurface.transform.position = PointerManager.m_Instance.MainPointer.transform.position; + m_SketchSurfacePanel.ResetReticleOffset(); + } + m_SurfaceLockActingController = InputManager.m_Instance.GetDominantController(InputManager.SketchCommands.LockToController); + m_SurfaceLockBaseSurfaceRotation = m_SketchSurface.transform.rotation; + m_SurfaceLockBaseControllerRotation = InputManager.m_Instance.GetControllerRotation(m_SurfaceLockActingController); + m_SurfaceLockBaseSurfacePosition = m_SketchSurface.transform.position; + m_SurfaceLockBaseControllerPosition = InputManager.m_Instance.GetControllerPosition(m_SurfaceLockActingController); + m_SurfaceLockControllerScalar = m_SketchSurfacePanel.m_PanelSensitivity / m_SurfaceLockControllerBaseScalar; + break; + case InputState.Save: + IssueGlobalCommand(GlobalCommands.Save); + break; + case InputState.Load: + IssueGlobalCommand(GlobalCommands.Load); + break; + } + + m_CurrentInputState = rDesiredState; + } + + public void RequestPanelsVisibility(bool bVisible) + { + // Always false in viewonly mode + bVisible = m_ViewOnly ? false : bVisible; + m_PanelsVisibilityRequested = bVisible; + } + + Quaternion OrientSketchSurfaceToUp() + { + //project the world up vector on to the surface plane + Vector3 vUpOnSurfacePlane = Vector3.up - (Vector3.Dot(Vector3.up, m_SurfaceForward) * m_SurfaceForward); + vUpOnSurfacePlane.Normalize(); + + //get the angle between the surface up and the projected world up + float fUpOnSurfacePlaneAngle = Vector3.Angle(vUpOnSurfacePlane, m_SurfaceUp); + Vector3 vUpCross = Vector3.Cross(vUpOnSurfacePlane, m_SurfaceUp); + vUpCross.Normalize(); + if (Vector3.Dot(vUpCross, m_SurfaceForward) > 0.0f) + { + fUpOnSurfacePlaneAngle *= -1.0f; + } + + //rotate around the surface foward by the angle diff + Quaternion qOrientToUp = Quaternion.AngleAxis(fUpOnSurfacePlaneAngle, m_SurfaceForward); + Quaternion qNewRotation = qOrientToUp * m_SketchSurface.transform.rotation; + return qNewRotation; + } + + Quaternion OrientSketchSurfaceToForward() + { + //project the world forward vector on to the surface plane + Vector3 vForwardOnSurfacePlane = Vector3.forward - (Vector3.Dot(Vector3.forward, m_SurfaceForward) * m_SurfaceForward); + vForwardOnSurfacePlane.Normalize(); + + //get the angle between the surface up and the projected world forward + float fForwardOnSurfacePlaneAngle = Vector3.Angle(vForwardOnSurfacePlane, m_SurfaceUp); + Vector3 vUpCross = Vector3.Cross(vForwardOnSurfacePlane, m_SurfaceUp); + vUpCross.Normalize(); + if (Vector3.Dot(vUpCross, m_SurfaceForward) > 0.0f) + { + fForwardOnSurfacePlaneAngle *= -1.0f; + } + + //rotate around the surface foward by the angle diff + Quaternion qOrientToForward = Quaternion.AngleAxis(fForwardOnSurfacePlaneAngle, m_SurfaceForward); + Quaternion qNewRotation = qOrientToForward * m_SketchSurface.transform.rotation; + return qNewRotation; + } + + /// Reset the scene or the canvas, depending on the current mode + public void ResetGrabbedPose(bool everything = false) + { + //update sketch surface position with offset to sweet spot + m_SketchSurface.transform.position = m_PanelManager.GetSketchSurfaceResetPos(); + if (everything) + { + App.Scene.Pose = TrTransform.identity; + Coords.CanvasLocalPose = TrTransform.identity; + } + App.Scene.Pose = TrTransform.identity; + + //reset orientation and pointer + ResetSketchSurfaceOrientation(); + m_SketchSurfacePanel.ResetReticleOffset(); + PointerManager.m_Instance.DisablePointerPreviewLine(); + PointerManager.m_Instance.SetPointerPreviewLineDelayTimer(); + } + + public void ResetSketchSurfaceOrientation() + { + m_SketchSurface.transform.rotation = Quaternion.identity; + m_SurfaceForward = m_SketchSurface.transform.forward; + m_SurfaceRight = m_SketchSurface.transform.right; + m_SurfaceUp = m_SketchSurface.transform.up; + } + + float GetAppropriateMovementScalar() + { + switch (m_CurrentInputState) + { + case InputState.Pan: return m_PanScalar; + case InputState.Rotation: return m_RotationScalar; + case InputState.PushPull: return m_PushPullScale; + } + + return 1.0f; + } + + // TODO - it'd be great if we could disentangle this from the multicam. + IEnumerator RenderPathAndQuit() + { +#if USD_SUPPORTED + App.Instance.SetDesiredState(App.AppState.OfflineRendering); + SketchSurfacePanel.m_Instance.EnableSpecificTool(BaseTool.ToolType.MultiCamTool); + MultiCamTool multiCam = SketchSurfacePanel.m_Instance.ActiveTool as MultiCamTool; + Debug.Assert(multiCam != null); // Something's gone wrong if we've been unable to find multicam! + if (multiCam == null) + { + yield break; + } + multiCam.ExternalObjectForceCameraStyle(MultiCamStyle.Video); + MultiCamCaptureRig.ForceClippingPlanes(MultiCamStyle.Video); + // Give the video tool time to switch - TODO - be a little more graceful here + yield return new WaitForSeconds(2); + // Make sure the videos have had time to load, and set playing ones to start + while (VideoCatalog.Instance.IsScanning) + { + yield return null; + } + foreach (var widget in WidgetManager.m_Instance.VideoWidgets) + { + if (widget.VideoController.Playing) + { + widget.VideoController.Position = 0; + } + } + yield return null; + var ssMgr = MultiCamCaptureRig.ManagerFromStyle(MultiCamStyle.Video); + ssMgr.SetScreenshotResolution(App.UserConfig.Video.OfflineResolution); + multiCam.StartVideoCapture(MultiCamTool.GetSaveName(MultiCamStyle.Video), offlineRender: true); + App.Instance.FrameCountDisplay.gameObject.SetActive(true); + App.Instance.FrameCountDisplay.SetFramesTotal(VideoRecorderUtils.NumFramesInUsdSerializer); + while (VideoRecorderUtils.ActiveVideoRecording != null) + { + App.Instance.FrameCountDisplay.SetCurrentFrame( + VideoRecorderUtils.ActiveVideoRecording.FrameCount); + yield return null; + } + ssMgr.SetScreenshotResolution(App.UserConfig.Video.Resolution); +#else + Debug.LogError("Render path requires USD support"); + yield return null; +#endif + QuitApp(); + } + + IEnumerator ExportListAndQuit() + { + App.Config.m_ForceDeterministicBirthTimeForExport = true; + List filesToExport = new List(); + foreach (string filePattern in App.Config.m_FilePatternsToExport) + { + bool absolute = Path.IsPathRooted(filePattern); + string directory = absolute ? Path.GetDirectoryName(filePattern) : App.UserSketchPath(); + string filename = Path.GetFileName(filePattern); + var tiltFiles = Directory.GetFiles(directory, filename); + filesToExport.AddRange(tiltFiles); + // Also look at .tilt files which have been unzipped into directory format + var tiltDirs = Directory.GetDirectories(directory, filename) + .Where(n => n.EndsWith(".tilt")); + filesToExport.AddRange(tiltDirs); + } + + using (var coroutine = LoadAndExportList(filesToExport)) + { + while (coroutine.MoveNext()) + { + yield return coroutine.Current; + } + } + QuitApp(); + } + + void QuitApp() + { + // We're done! Quit! +#if UNITY_EDITOR + UnityEditor.EditorApplication.isPlaying = false; +#else + Application.Quit(); +#endif + } + + // This coroutine must be run to completion or disposed. + IEnumerator LoadAndExportList(List filenames) + { + foreach (var filename in filenames) + { + using (var coroutine = LoadAndExport(filename)) + { + while (coroutine.MoveNext()) + { + yield return coroutine.Current; + } + } + } + } + + // This coroutine must be run to completion or disposed. + IEnumerator LoadAndExportAll() + { + SketchSet sketchSet = SketchCatalog.m_Instance.GetSet(SketchSetType.User); + for (int i = 0; i < SketchCatalog.m_Instance.GetSet(SketchSetType.User).NumSketches; ++i) + { + SceneFileInfo rInfo = sketchSet.GetSketchSceneFileInfo(i); + using (var coroutine = LoadAndExport(rInfo.FullPath)) + { + while (coroutine.MoveNext()) + { + yield return coroutine.Current; + } + } + } + } + + /// Loads a .tilt file completely. + /// This may be slightly buggy; it's not currently used for production. + /// This coroutine must be run to completion or disposed. + public IEnumerable LoadTiltFile(string filename) + { + using (var unused = new SceneSettings.RequestInstantSceneSwitch()) + { + IssueGlobalCommand( + GlobalCommands.LoadNamedFile, + iParam1: (int)LoadSpeed.Quick, sParam: filename); + yield return null; + while (App.Instance.IsLoading()) + { + yield return null; + } + + // I don't know why App.Instance.IsLoading() doesn't cover this, but it doesn't. + while (m_WidgetManager.CreatingMediaWidgets) + { + yield return null; + } + while (WidgetManager.m_Instance.AreMediaWidgetsStillLoading()) + { + yield return null; + } + + // This is kind of a hack. + // Despite the RequestInstantSceneSwitch above, I think scene colors still require + // a few frames to settle; also, GrabWidgets need to register themselves on the + // first frame, etc. + for (int i = 0; i < 10; ++i) + { + yield return null; + } + } + } + + // This coroutine must be run to completion or disposed. + IEnumerator LoadAndExport(string filename) + { + foreach (var val in LoadTiltFile(filename)) + { + yield return val; + } + using (var coroutine = ExportCoroutine()) + { + while (coroutine.MoveNext()) + { + yield return coroutine.Current; + } + } + } + + IEnumerator ExportCoroutine() + { + return OverlayManager.m_Instance.RunInCompositor( + OverlayType.Export, () => + { + // Sort of a kludge: put stuff back into the main canvas + SelectionManager.m_Instance.ClearActiveSelection(); + Export.ExportScene(); + }, 0.25f, false, true); + } + + private void SaveModel() + { +#if USD_SUPPORTED + var current = SaveLoadScript.m_Instance.SceneFile; + string basename = (current.Valid) + ? Path.GetFileNameWithoutExtension(current.FullPath) + : "Untitled"; + string directoryName = FileUtils.GenerateNonexistentFilename( + App.ModelLibraryPath(), basename, ""); + + string usdname = Path.Combine(directoryName, basename + ".usd"); + // TODO: export selection only, though this is still only experimental. The blocking + // issue to implement this is that the export collector needs to expose this as an option. + // + // SelectionManager.m_Instance.HasSelection + // ? SelectionManager.m_Instance.SelectedStrokes + // : null + ExportUsd.ExportPayload(usdname); + OutputWindowScript.m_Instance.CreateInfoCardAtController( + InputManager.ControllerName.Brush, "Model created!"); +#endif + } + + /// Generates a view from the previous thumbnail viewpoint. + public void GenerateReplacementSaveIcon() + { + if (SaveLoadScript.m_Instance.LastThumbnail_SS.HasValue) + { + TrTransform thumbnailInGlobalSpace = App.Scene.Pose * + SaveLoadScript.m_Instance.LastThumbnail_SS.Value; + + m_SaveIconTool.ProgrammaticCaptureSaveIcon(thumbnailInGlobalSpace.translation, + thumbnailInGlobalSpace.rotation); + } + else + { + GenerateBestGuessSaveIcon(); + } + } + + public void GenerateBestGuessSaveIcon() + { + TrTransform camXform = GenerateBestGuessSaveIconTransform(); + m_SaveIconTool.ProgrammaticCaptureSaveIcon(camXform.translation, camXform.rotation); + } + + /// This positions the save icon camera at the user's head position, and faces it towards + /// the most recent strokes the user has created. + /// If there are no strokes, it faces towards the 'most recent' models. + /// Sadly we cannot really mix the two as we don't know when the models were instantiated. + public TrTransform GenerateBestGuessSaveIconTransform(int itemsToEnumerate = 0) + { + if (itemsToEnumerate == 0) + { + itemsToEnumerate = m_NumStrokesForSaveIcon; + } + int startIndex = Mathf.Max(0, SketchMemoryScript.AllStrokesCount() - itemsToEnumerate); + var lastFewStrokes = SketchMemoryScript.AllStrokes().Skip(startIndex).ToArray(); + + Bounds bounds; + if (lastFewStrokes.Length > 0) + { + bounds = new Bounds(lastFewStrokes.First().m_ControlPoints.First().m_Pos, Vector3.zero); + foreach (var stroke in lastFewStrokes.Skip(1)) + { + bounds.Encapsulate(stroke.m_ControlPoints.First().m_Pos); + bounds.Encapsulate(stroke.m_ControlPoints.Last().m_Pos); + } + } + else + { + // If we have no strokes, just use the aggregates bounding boxes of the blocks models. + var models = m_WidgetManager.ModelWidgets.ToArray(); + // we should always have models to get here, but just in case... + if (models.Length > 0) + { + startIndex = Mathf.Max(0, models.Length - itemsToEnumerate); + bounds = models[startIndex].WorldSpaceBounds; + for (int i = startIndex + 1; i < models.Length; ++i) + { + bounds.Encapsulate(models[i].WorldSpaceBounds); + } + } + else + { + bounds = new Bounds(new Vector3(0, 1, -100000), Vector3.one); // some point in the distance + } + } + + Vector3 camPos = ViewpointScript.Head.position; + Vector3 worldPos = App.Scene.Pose.MultiplyPoint(bounds.center); + Quaternion direction = Quaternion.LookRotation(worldPos - camPos); + return TrTransform.TR(camPos, direction); + } + + + public void GenerateBoundingBoxSaveIcon() + { + Vector3 vNewCamPos; + { + Bounds rCanvasBounds = App.Scene.AllCanvases + .Select(canvas => canvas.GetCanvasBoundingBox()) + .Aggregate((b1, b2) => + { + b1.Encapsulate(b2); + return b1; + }); + + //position the camera at the center of the canvas bounds + vNewCamPos = rCanvasBounds.center; + + //back the camera up, along -z until we can see the extent of the bounds + float fCanvasWidth = rCanvasBounds.max.x - rCanvasBounds.min.x; + float fCanvasHeight = rCanvasBounds.max.y - rCanvasBounds.min.y; + float fLargerExtent = Mathf.Max(fCanvasHeight, fCanvasWidth); + + //half fov for camera + float fHalfFOV = m_SaveIconTool.ScreenshotManager.LeftEye.fieldOfView * 0.5f; + + //TODO: find the real reason this isn't working as it should + float fMagicNumber = 1.375f; + + //set new cam position and zero out orientation + float fBackupDistance = (fLargerExtent * 0.5f) + * Mathf.Tan(Mathf.Deg2Rad * fHalfFOV) * fMagicNumber; + vNewCamPos.z = rCanvasBounds.min.z - fBackupDistance; + } + + m_SaveIconTool.ProgrammaticCaptureSaveIcon(vNewCamPos, Quaternion.identity); + } + + private void MergeBrushStrokes(SceneFileInfo fileInfo) + { + m_PanelManager.ToggleSketchbookPanels(isLoadingSketch: true); + PointerManager.m_Instance.EnablePointerStrokeGeneration(true); + if (SaveLoadScript.m_Instance.Load(fileInfo, true)) + { + SketchMemoryScript.m_Instance.SetPlaybackMode(m_SketchPlaybackMode, m_DefaultSketchLoadSpeed); + SketchMemoryScript.m_Instance.BeginDrawingFromMemory(bDrawFromStart: true, false, false); + // the order of these two lines are important as ExitIntroSketch is setting the + // color of the pointer and we need the color to be set before we go to the Loading + // state. App script's ShouldTintControllers allow the controller to be tinted only + // when the app is in the standard mode. That was there to prevent the controller color + // from flickering while in the intro mode. + App.Instance.ExitIntroSketch(); + App.Instance.SetDesiredState(App.AppState.QuickLoad); + } + } + + public void LoadSketch(SceneFileInfo fileInfo, bool quickload = false, bool additive = false) + { + LightsControlScript.m_Instance.DiscoMode = false; + m_WidgetManager.FollowingPath = false; + m_WidgetManager.CameraPathsVisible = false; + m_WidgetManager.DestroyAllWidgets(); + m_PanelManager.ToggleSketchbookPanels(isLoadingSketch: true); + ResetGrabbedPose(everything: true); + PointerManager.m_Instance.EnablePointerStrokeGeneration(true); + if (SaveLoadScript.m_Instance.Load(fileInfo, additive)) + { + SketchMemoryScript.m_Instance.SetPlaybackMode(m_SketchPlaybackMode, m_DefaultSketchLoadSpeed); + SketchMemoryScript.m_Instance.BeginDrawingFromMemory(bDrawFromStart: true); + // the order of these two lines are important as ExitIntroSketch is setting the + // color of the pointer and we need the color to be set before we go to the Loading + // state. App script's ShouldTintControllers allow the controller to be tinted only + // when the app is in the standard mode. That was there to prevent the controller color + // from flickering while in the intro mode. + App.Instance.ExitIntroSketch(); + App.Instance.SetDesiredState(quickload ? App.AppState.QuickLoad : App.AppState.Loading); + } + QualityControls.m_Instance.ResetAutoQuality(); + m_WidgetManager.ValidateCurrentCameraPath(); + } + + public void IssueGlobalCommand(GlobalCommands rEnum, int iParam1 = -1, + int iParam2 = -1, string sParam = null) + { + switch (rEnum) + { + + // Keyboard command, for debugging and emergency use. + case GlobalCommands.Save: + { + if (!FileUtils.CheckDiskSpaceWithError(App.UserSketchPath())) + { + return; + } + // Disable active selection before saving. + // This looks fishy, here's what's going on: When an object is selected and it has moved, the + // the user is observing the selection canvas in the HMD, but we will be saving the main canvas. + // Because they haven't deselected yet, the selection canvas and the main canvas are out of sync + // so the strokes that will be saved will not match what the user sees. + // + // Here we deselect to force the main canvas to sync with the selection canvas, which is more + // correct from the user's perspective. Push the deselect operation onto the stack so the user + // can undo it after save, if desired. + SelectionManager.m_Instance.ClearActiveSelection(); + GenerateReplacementSaveIcon(); + if (iParam1 == -1) + { + if (iParam2 == 1) + { + // Do a save in Tiltasaurus mode, which creates a new filename prefixed with + // "Tiltasaurus_" and the current prompt. Also, don't eat gaze input so that the + // Tiltasaurus prompt stays open. + StartCoroutine(SaveLoadScript.m_Instance.SaveOverwrite(tiltasaurusMode: true)); + } + else + { + StartCoroutine(SaveLoadScript.m_Instance.SaveOverwrite()); + EatGazeObjectInput(); + } + } + else + { + StartCoroutine(SaveLoadScript.m_Instance.SaveMonoscopic(iParam1)); + } + break; + } + case GlobalCommands.SaveNew: + { + if (!FileUtils.CheckDiskSpaceWithError(App.UserSketchPath())) + { + return; + } + if (iParam1 == 1) + { + GenerateBoundingBoxSaveIcon(); + } + StartCoroutine(SaveLoadScript.m_Instance.SaveNewName()); + EatGazeObjectInput(); + break; + } + case GlobalCommands.SaveAndUpload: + { + if (!FileUtils.CheckDiskSpaceWithError(App.UserSketchPath())) + { + Debug.LogError("SaveAndUpload: Disk space error"); + return; + } + SelectionManager.m_Instance.ClearActiveSelection(); + m_PanelManager.GetPanel(m_CurrentGazeObject).CreatePopUp( + GlobalCommands.UploadToGenericCloud, (int)Cloud.None, -1); + EatGazeObjectInput(); + break; + } + case GlobalCommands.ExportAll: + { + StartCoroutine(LoadAndExportAll()); + break; + } + // Glen Keane request: a way to draw guidelines that can be toggled on and off + // at runtime. + case GlobalCommands.DraftingVisibility: + { + if (!Enum.IsDefined(typeof(DraftingVisibilityOption), iParam1)) + { + Debug.LogError("Unknown draft visibility value: " + iParam1); + return; + } + DraftingVisibilityOption option = (DraftingVisibilityOption)iParam1; + if (option != m_DraftingVisibility) + { + m_DraftingVisibility = option; + UpdateDraftingVisibility(); + } + break; + } + case GlobalCommands.MergeBrushStrokes: + { + // TODO Refactor with Load below + var index = iParam1; + var sketchSetType = (SketchSetType)iParam2; + SketchSet sketchSet = SketchCatalog.m_Instance.GetSet(sketchSetType); + SceneFileInfo rInfo = sketchSet.GetSketchSceneFileInfo(index); + if (rInfo != null) + { + MergeBrushStrokes(rInfo); + if (m_ControlsType != ControlsType.ViewingOnly) + { + EatGazeObjectInput(); + } + } + break; + } + case GlobalCommands.Load: + { + var index = iParam1; + var sketchSetType = (SketchSetType)iParam2; + SketchSet sketchSet = SketchCatalog.m_Instance.GetSet(sketchSetType); + SceneFileInfo rInfo = sketchSet.GetSketchSceneFileInfo(index); + if (rInfo != null) + { + LoadSketch(rInfo); + if (m_ControlsType != ControlsType.ViewingOnly) + { + EatGazeObjectInput(); + } + } + break; + } + case GlobalCommands.LoadNamedFile: + LoadNamed(sParam, iParam1 == (int)LoadSpeed.Quick, iParam2 != -1); + break; + case GlobalCommands.NewSketch: + NewSketch(fade: true); + Vector3 vTrashSoundPos = m_CurrentGazeRay.origin; + if (App.VrSdk.GetControllerDof() == VrSdk.DoF.Six) + { + vTrashSoundPos = InputManager.m_Instance.GetControllerPosition( + InputManager.ControllerName.Wand); + } + AudioManager.m_Instance.PlayTrashSound(vTrashSoundPos); + PromoManager.m_Instance.RequestAdvancedPanelsPromo(); + break; + case GlobalCommands.SymmetryPlane: + if (PointerManager.m_Instance.CurrentSymmetryMode != SymmetryMode.SinglePlane) + { + PointerManager.m_Instance.SetSymmetryMode(SymmetryMode.SinglePlane); + ControllerConsoleScript.m_Instance.AddNewLine("Mirror Enabled"); + } + else + { + PointerManager.m_Instance.SetSymmetryMode(SymmetryMode.None); + ControllerConsoleScript.m_Instance.AddNewLine("Mirror Off"); + } + break; + case GlobalCommands.MultiMirror: + if (PointerManager.m_Instance.CurrentSymmetryMode != SymmetryMode.MultiMirror) + { + PointerManager.m_Instance.SetSymmetryMode(SymmetryMode.MultiMirror); + ControllerConsoleScript.m_Instance.AddNewLine("Symmetry Enabled"); + } + else + { + PointerManager.m_Instance.SetSymmetryMode(SymmetryMode.None); + ControllerConsoleScript.m_Instance.AddNewLine("Symmetry Off"); + } + InputManager.m_Instance.TriggerHaptics(InputManager.ControllerName.Brush, 0.1f); + break; + case GlobalCommands.SymmetryTwoHanded: + if (PointerManager.m_Instance.CurrentSymmetryMode != SymmetryMode.TwoHanded) + { + PointerManager.m_Instance.SetSymmetryMode(SymmetryMode.TwoHanded); + ControllerConsoleScript.m_Instance.AddNewLine("Symmetry Enabled"); + } + else + { + PointerManager.m_Instance.SetSymmetryMode(SymmetryMode.None); + ControllerConsoleScript.m_Instance.AddNewLine("Symmetry Off"); + } + InputManager.m_Instance.TriggerHaptics(InputManager.ControllerName.Brush, 0.1f); + break; + case GlobalCommands.StraightEdge: + PointerManager.m_Instance.StraightEdgeModeEnabled = !PointerManager.m_Instance.StraightEdgeModeEnabled; + if (PointerManager.m_Instance.StraightEdgeModeEnabled) + { + ControllerConsoleScript.m_Instance.AddNewLine("Straight Edge On"); + } + else + { + ControllerConsoleScript.m_Instance.AddNewLine("Straight Edge Off"); + } + break; + case GlobalCommands.AutoOrient: + m_AutoOrientAfterRotation = !m_AutoOrientAfterRotation; + if (m_AutoOrientAfterRotation) + { + ControllerConsoleScript.m_Instance.AddNewLine("Auto-Orient On"); + } + else + { + ControllerConsoleScript.m_Instance.AddNewLine("Auto-Orient Off"); + } + break; + case GlobalCommands.Undo: + SketchMemoryScript.m_Instance.StepBack(); + break; + case GlobalCommands.Redo: + SketchMemoryScript.m_Instance.StepForward(); + break; + case GlobalCommands.AudioVisualization: // Intentionally blank. + break; + case GlobalCommands.ResetAllPanels: + m_PanelManager.ResetWandPanelsConfiguration(); + EatGazeObjectInput(); + break; + case GlobalCommands.SketchOrigin: + m_SketchSurfacePanel.EnableSpecificTool(BaseTool.ToolType.SketchOrigin); + EatGazeObjectInput(); + break; + case GlobalCommands.ViewOnly: + m_ViewOnly = !m_ViewOnly; + RequestPanelsVisibility(!m_ViewOnly); + PointerManager.m_Instance.RequestPointerRendering(!m_ViewOnly); + // TODO - decide if this is a permanent change + // With this line, you can't set a tool such as fly or teleport + // and switch to View Only mode as the mode change disables all tools + //m_SketchSurface.SetActive(!m_ViewOnly); + m_Decor.SetActive(!m_ViewOnly); + break; + case GlobalCommands.SaveGallery: + m_SketchSurfacePanel.EnableSpecificTool(BaseTool.ToolType.SaveIconTool); + break; + case GlobalCommands.DropCam: + // Want to enable this if in monoscopic or VR modes. + // TODO: seems odd to tie this switch to the controller type, should be based on some + // other build-time configuration setting. + if (App.VrSdk.GetControllerDof() != VrSdk.DoF.None) + { + m_DropCam.Show(!m_DropCam.gameObject.activeSelf); + } + break; + case GlobalCommands.AnalyticsEnabled_Deprecated: + break; + case GlobalCommands.ToggleAutosimplification: + QualityControls.AutosimplifyEnabled = !QualityControls.AutosimplifyEnabled; + break; + case GlobalCommands.Credits: + LoadSketch(new DiskSceneFileInfo(m_CreditsSketchFilename, embedded: true, readOnly: true)); + EatGazeObjectInput(); + break; + case GlobalCommands.AshleysSketch: + LoadSketch(new DiskSceneFileInfo(m_AshleysSketchFilename, embedded: true, readOnly: true)); + EatGazeObjectInput(); + break; + case GlobalCommands.FAQ: + OpenURLAndInformUser(m_HelpCenterURL); + break; + case GlobalCommands.ReleaseNotes: + OpenURLAndInformUser(m_ReleaseNotesURL); + break; + case GlobalCommands.ExportRaw: + if (!FileUtils.CheckDiskSpaceWithError(App.UserExportPath())) + { + return; + } + EatGazeObjectInput(); + StartCoroutine(ExportCoroutine()); + break; + case GlobalCommands.IRC: + if (m_IRCChatWidget == null) + { + GameObject widgetobject = (GameObject)Instantiate(m_IRCChatPrefab); + widgetobject.transform.parent = App.Instance.m_RoomTransform; + m_IRCChatWidget = widgetobject.GetComponent(); + m_IRCChatWidget.Show(true); + } + else + { + m_IRCChatWidget.Show(false); + m_IRCChatWidget = null; + } + break; + case GlobalCommands.YouTubeChat: + if (m_YouTubeChatWidget == null) + { + GameObject widgetobject = (GameObject)Instantiate(m_YouTubeChatPrefab); + widgetobject.transform.parent = App.Instance.m_RoomTransform; + m_YouTubeChatWidget = widgetobject.GetComponent(); + m_YouTubeChatWidget.Show(true); + } + else + { + m_YouTubeChatWidget.Show(false); + m_YouTubeChatWidget = null; + } + break; + case GlobalCommands.CameraOptions: + // If we're switching in to Camera mode, make sure Multicam is selected. + if (!m_PanelManager.CameraActive()) + { + SketchSurfacePanel.m_Instance.EnableSpecificTool(BaseTool.ToolType.MultiCamTool); + } + m_PanelManager.ToggleCameraPanels(); + PointerManager.m_Instance.EatLineEnabledInput(); + SketchSurfacePanel.m_Instance.EatToolsInput(); + break; + case GlobalCommands.ShowSketchFolder: + { + var index = iParam1; + var sketchSetType = (SketchSetType)iParam2; + SketchSet sketchSet = SketchCatalog.m_Instance.GetSet(sketchSetType); + SceneFileInfo rInfo = sketchSet.GetSketchSceneFileInfo(index); + EatGazeObjectInput(); + //launch external window and tell the user we did so + //this call is windows only + if ((Application.platform == RuntimePlatform.WindowsPlayer) || + (Application.platform == RuntimePlatform.WindowsEditor)) + { + OutputWindowScript.m_Instance.CreateInfoCardAtController( + InputManager.ControllerName.Brush, + kRemoveHeadsetFyi, fPopScalar: 0.5f); + System.Diagnostics.Process.Start("explorer.exe", + "/select," + rInfo.FullPath); + } + break; + } + case GlobalCommands.About: + OpenURLAndInformUser(m_ThirdPartyNoticesURL); + break; + case GlobalCommands.StencilsDisabled: + SketchMemoryScript.m_Instance.PerformAndRecordCommand(new StencilsVisibleCommand()); + break; + case GlobalCommands.StraightEdgeMeterDisplay: + PointerManager.m_Instance.StraightEdgeGuide.FlipMeter(); + break; + case GlobalCommands.Sketchbook: + m_PanelManager.ToggleSketchbookPanels(); + PointerManager.m_Instance.EatLineEnabledInput(); + SketchSurfacePanel.m_Instance.EatToolsInput(); + break; + case GlobalCommands.StraightEdgeShape: + // Previously experimental mode only. + // Untested and currently untriggerable. + PointerManager.m_Instance.StraightEdgeGuide.SetTempShape( + (StraightEdgeGuideScript.Shape)iParam1); + break; + case GlobalCommands.DeleteSketch: + { + var sketchSetType = (SketchSetType)iParam2; + SketchSet sketchSet = SketchCatalog.m_Instance.GetSet(sketchSetType); + sketchSet.DeleteSketch(iParam1); + DismissPopupOnCurrentGazeObject(false); + break; + } + case GlobalCommands.RenameSketch: + { + var sketchSetType = (SketchSetType)iParam2; + SketchSet sketchSet = SketchCatalog.m_Instance.GetSet(sketchSetType); + string newName = sParam; + if (string.IsNullOrEmpty(newName)) + { + newName = KeyboardPopUpWindow.m_LastInput; + if (string.IsNullOrEmpty(newName)) + { + break; + } + } + + if (sketchSetType == SketchSetType.User) + { + sketchSet.RenameSketch(iParam1, newName); + } + DismissPopupOnCurrentGazeObject(false); + break; + } + case GlobalCommands.RenameLayer: + { + var layer = App.Scene.GetCanvasByLayerIndex(iParam1); + App.Scene.RenameLayer(layer, KeyboardPopUpWindow.m_LastInput); + DismissPopupOnCurrentGazeObject(false); + break; + } + case GlobalCommands.ShowWindowGUI: + break; + case GlobalCommands.Disco: + LightsControlScript.m_Instance.DiscoMode = !LightsControlScript.m_Instance.DiscoMode; + break; + case GlobalCommands.AccountInfo: break; // Intentionally blank. + case GlobalCommands.LoginToGenericCloud: + { + var ident = App.GetIdentity((Cloud)iParam1); + if (!ident.LoggedIn) { ident.LoginAsync(); } + // iParam2 is being used as a UX flag. If not set to the default, it will cause the UI + // to lose focus. + if (iParam2 != -1) { EatGazeObjectInput(); } + break; + } + case GlobalCommands.LogOutOfGenericCloud: + { + Cloud cloud = (Cloud)iParam1; + if (cloud == Cloud.Icosa) + { + App.Instance.IcosaToken = null; + App.IcosaUserName = ""; + App.IcosaUserIcon = null; + } + else + { + var ident = App.GetIdentity(cloud); + if (ident.LoggedIn) { ident.Logout(); } + } + break; + } + case GlobalCommands.UploadToGenericCloud: + { + Cloud cloud = (Cloud)iParam1; + if (cloud == Cloud.Icosa) + { + if (App.Instance.IcosaToken == null) + { + OutputWindowScript.m_Instance.CreateInfoCardAtController( + InputManager.ControllerName.Brush, + "Not logged in", fPopScalar: 0.5f); + } + } + else + { + var ident = App.GetIdentity(cloud); + if (!ident.LoggedIn) + { + ident.LoginAsync(); + break; + } + } + SelectionManager.m_Instance.ClearActiveSelection(); + VrAssetService.m_Instance.UploadCurrentSketchAsync(cloud, isDemoUpload: false).AsAsyncVoid(); + EatGazeObjectInput(); + break; + } + case GlobalCommands.ViewOnlineGallery: + OpenURLAndInformUser(m_OpenBrushGalleryUrl); + break; + case GlobalCommands.CancelUpload: + VrAssetService.m_Instance.CancelUpload(); + break; + case GlobalCommands.ViewLastUpload: + if (VrAssetService.m_Instance.LastUploadCompleteUrl != null) + { + var url = VrAssetService.m_Instance.LastUploadCompleteUrl; + App.OpenURL(url); + + // The upload flow is different on mobile and requires the user to manually accept + // that they'll go to the browser for publishing. In that case, we want to reset + // state when the leave to publish. This is automatically part of the + // UploadPopUpWindow state flow on PC. + if (App.Config.IsMobileHardware) + { + DismissPopupOnCurrentGazeObject(true); + } + } + break; + case GlobalCommands.ShowGoogleDrive: + string baseDriveUrl = "https://drive.google.com"; + string driveURL = !App.GoogleIdentity.LoggedIn ? baseDriveUrl : + string.Format( + "http://accounts.google.com/AccountChooser?Email={0}&continue={1}", + App.GoogleIdentity.Profile.email, baseDriveUrl); + OpenURLAndInformUser(driveURL); + break; + case GlobalCommands.GoogleDriveSync: + App.DriveSync.SyncEnabled = !App.DriveSync.SyncEnabled; + break; + case GlobalCommands.GoogleDriveSync_Folder: + App.DriveSync.ToggleSyncOnFolderOfType((DriveSync.SyncedFolderType)iParam1); + break; + case GlobalCommands.Duplicate: + { + int selectedVerts = SelectionManager.m_Instance.NumVertsInSelection; + + // TODO - this code has never taken imported models etc into account + if (PointerManager.m_Instance.CurrentSymmetryMode == SymmetryMode.MultiMirror) + { + selectedVerts *= PointerManager.m_Instance.CustomMirrorMatrices.Count; + } + + if (!SketchMemoryScript.m_Instance.MemoryWarningAccepted && + SketchMemoryScript.m_Instance.WillVertCountPutUsOverTheMemoryLimit(selectedVerts)) + { + AudioManager.m_Instance.PlayUploadCanceledSound(InputManager.Wand.Transform.position); + if (!m_PanelManager.MemoryWarningActive()) + { + m_PanelManager.ToggleMemoryWarningMode(); + } + } + else + { + ClipboardManager.Instance.DuplicateSelection( + stampMode: IsUserInteractingWithSelectionWidget()); + } + EatToolScaleInput(); + break; + } + case GlobalCommands.AdvancedPanelsToggle: + m_PanelManager.ToggleAdvancedPanels(); + // If we're now in basic mode, ensure we don't have advanced abilities. + if (!m_PanelManager.AdvancedModeActive()) + { + m_WidgetManager.StencilsDisabled = true; + m_WidgetManager.CameraPathsVisible = false; + App.Switchboard.TriggerStencilModeChanged(); + m_SketchSurfacePanel.EnsureUserHasBasicToolEnabled(); + if (PointerManager.m_Instance.CurrentSymmetryMode != SymmetryMode.None) + { + PointerManager.m_Instance.SetSymmetryMode(SymmetryMode.None, false); + } + } + PromoManager.m_Instance.RecordCompletion(PromoType.AdvancedPanels); + EatGazeObjectInput(); + break; + case GlobalCommands.Music: break; // Intentionally blank. + case GlobalCommands.ToggleGroupStrokesAndWidgets: + SelectionManager.m_Instance.ToggleGroupSelectedStrokesAndWidgets(); + EatToolScaleInput(); + break; + case GlobalCommands.SaveModel: + SaveModel(); + break; + case GlobalCommands.ViewIcosaHomePage: + OpenURLAndInformUser(VrAssetService.m_Instance.IcosaHomePage); + break; + case GlobalCommands.ViewBlocksGallery: + OpenURLAndInformUser(m_BlocksGalleryUrl); + break; + case GlobalCommands.ExportListed: + StartCoroutine(ExportListAndQuit()); + break; + case GlobalCommands.RenderCameraPath: + StartCoroutine(RenderPathAndQuit()); + break; + case GlobalCommands.ToggleProfiling: + ToggleProfiling(); + break; + case GlobalCommands.DoAutoProfile: + DoAutoProfile(); + break; + case GlobalCommands.DoAutoProfileAndQuit: + DoAutoProfileAndQuit(); + break; + case GlobalCommands.ToggleSettings: + m_PanelManager.ToggleSettingsPanels(); + PointerManager.m_Instance.EatLineEnabledInput(); + SketchSurfacePanel.m_Instance.EatToolsInput(); + break; + case GlobalCommands.SummonMirror: + PointerManager.m_Instance.BringSymmetryToUser(); + break; + case GlobalCommands.InvertSelection: + SelectionManager.m_Instance.InvertSelection(); + break; + case GlobalCommands.SelectAll: + SketchSurfacePanel.m_Instance.EnableSpecificTool(BaseTool.ToolType.SelectionTool); + SelectionManager.m_Instance.SelectAll(); + EatGazeObjectInput(); + break; + case GlobalCommands.FlipSelection: + SelectionManager.m_Instance.FlipSelection(); + break; + case GlobalCommands.ToggleBrushLab: + m_PanelManager.ToggleBrushLabPanels(); + PointerManager.m_Instance.EatLineEnabledInput(); + SketchSurfacePanel.m_Instance.EatToolsInput(); + break; + case GlobalCommands.ToggleCameraPostEffects: + CameraConfig.PostEffects = !CameraConfig.PostEffects; + break; + case GlobalCommands.ToggleWatermark: + if (PlayerPrefs.GetInt("Promo_Contribution", 0) == 0) + { + OutputWindowScript.m_Instance.CreateInfoCardAtController( + InputManager.ControllerName.Wand, + m_ContributionPromoText, fPopScalar: 1.0f); + PlayerPrefs.SetInt("Promo_Contribution", 1); + } + CameraConfig.Watermark = !CameraConfig.Watermark; + break; + case GlobalCommands.LoadConfirmComplexHigh: + IssueGlobalCommand(GlobalCommands.Load, iParam1, iParam2, null); + break; + case GlobalCommands.LoadConfirmComplex: + { + var index = iParam1; + var sketchSetType = (SketchSetType)iParam2; + bool loadSketch = true; + + // If the sketchbook is active, we may want to show a popup instead of load. + if (m_PanelManager.SketchbookActive()) + { + BasePanel sketchBook = m_PanelManager.GetSketchBookPanel(); + if (sketchBook != null) + { + // Get triangle count from cloud scene file info. + SketchSet sketchSet = SketchCatalog.m_Instance.GetSet(sketchSetType); + SceneFileInfo sfi = sketchSet.GetSketchSceneFileInfo(index); + int tris = sfi.TriangleCount ?? -1; + + // Show "this is bad" popup if we're over the triangle limit. + if (tris > QualityControls.m_Instance.AppQualityLevels.MaxPolySketchTriangles) + { + loadSketch = false; + sketchBook.CreatePopUp(GlobalCommands.LoadConfirmComplexHigh, iParam1, iParam2); + } + else if (tris > + QualityControls.m_Instance.AppQualityLevels.WarningPolySketchTriangles) + { + // Show, "this could be bad" popup if we're over the warning limit. + loadSketch = false; + sketchBook.CreatePopUp(GlobalCommands.Load, iParam1, iParam2); + } + } + } + + if (loadSketch) + { + IssueGlobalCommand(GlobalCommands.Load, iParam1, iParam2, null); + } + } + break; + case GlobalCommands.LoadConfirmUnsaved: + { + BasePanel sketchBook = m_PanelManager.GetSketchBookPanel(); + if ((sketchBook != null) && SketchMemoryScript.m_Instance.IsMemoryDirty()) + { + sketchBook.CreatePopUp(GlobalCommands.LoadWaitOnDownload, iParam1, iParam2, null); + } + else + { + IssueGlobalCommand(GlobalCommands.LoadWaitOnDownload, iParam1, iParam2, null); + } + } + break; + case GlobalCommands.LoadWaitOnDownload: + { + bool download = false; + if (iParam2 == (int)SketchSetType.Drive) + { + BasePanel sketchBook = m_PanelManager.GetSketchBookPanel(); + var googleSketchSet = SketchCatalog.m_Instance.GetSet(SketchSetType.Drive); + if (sketchBook != null + && googleSketchSet != null + && googleSketchSet.IsSketchIndexValid(iParam1) + && !googleSketchSet.GetSketchSceneFileInfo(iParam1).Available) + { + sketchBook.CreatePopUp(GlobalCommands.LoadConfirmComplex, iParam1, iParam2, null); + download = true; + } + } + if (!download) + { + IssueGlobalCommand(GlobalCommands.LoadConfirmComplex, iParam1, iParam2, null); + } + } + break; + case GlobalCommands.MemoryWarning: + if (iParam1 > 0) + { + SketchMemoryScript.m_Instance.MemoryWarningAccepted = true; + } + m_PanelManager.ToggleMemoryWarningMode(); + break; + case GlobalCommands.MemoryExceeded: + // If we're in the memory exceeded app state, exit. + if (App.CurrentState == App.AppState.MemoryExceeded) + { + App.Instance.SetDesiredState(App.AppState.Standard); + } + else + { + // If we're not in the full app state, just switch our panel mode. + m_PanelManager.ToggleMemoryWarningMode(); + } + break; + case GlobalCommands.ShowTos: + OpenURLAndInformUser(m_TosURL); + break; + case GlobalCommands.ShowPrivacy: + OpenURLAndInformUser(m_PrivacyURL); + break; + case GlobalCommands.ShowQuestSideLoading: + OpenURLAndInformUser(m_QuestSideLoadingHowToURL); + break; + case GlobalCommands.ShowContribution: + OpenURLAndInformUser(m_ContributionURL); + break; + case GlobalCommands.UnloadReferenceImageCatalog: + ReferenceImageCatalog.m_Instance.UnloadAllImages(); + break; + case GlobalCommands.ToggleCameraPathVisuals: + m_WidgetManager.CameraPathsVisible = !m_WidgetManager.CameraPathsVisible; + break; + case GlobalCommands.ToggleCameraPathPreview: + m_WidgetManager.FollowingPath = !m_WidgetManager.FollowingPath; + break; + case GlobalCommands.DeleteCameraPath: + { + var cameraPath = m_WidgetManager.GetCurrentCameraPath(); + GrabWidget cameraPathWidget = cameraPath == null ? null : cameraPath.m_WidgetScript; + m_WidgetManager.DeleteCameraPath(cameraPathWidget); + } + break; + case GlobalCommands.RecordCameraPath: + // Turn off MultiCam if we're going to record the camera path. + if (m_SketchSurfacePanel.GetCurrentToolType() == BaseTool.ToolType.MultiCamTool) + { + m_SketchSurfacePanel.EnableDefaultTool(); + } + CameraPathCaptureRig.RecordPath(); + EatGazeObjectInput(); + break; + case GlobalCommands.OpenScriptsCommandsList: + OpenURLAndInformUser($"http://localhost:{App.HttpServer.HttpPort}/help/commands"); + break; + case GlobalCommands.OpenScriptsList: + OpenURLAndInformUser($"http://localhost:{App.HttpServer.HttpPort}/scripts"); + break; + case GlobalCommands.OpenExampleScriptsList: + OpenURLAndInformUser($"http://localhost:{App.HttpServer.HttpPort}/examplescripts"); + break; + case GlobalCommands.RepaintOptions: break; // Intentionally blank. + case GlobalCommands.LoginToIcosa: break; // Intentionally blank. + case GlobalCommands.Null: break; // Intentionally blank. + default: + Debug.LogError($"Unrecognized command {rEnum}"); + break; + } + } + + private void LoadNamed(string path, bool quickload, bool additive) + { + var fileInfo = new DiskSceneFileInfo(path); + fileInfo.ReadMetadata(); + if (SaveLoadScript.m_Instance.LastMetadataError != null) + { + ControllerConsoleScript.m_Instance.AddNewLine( + string.Format("Error detected in sketch '{0}'.\nTry re-saving.", + fileInfo.HumanName)); + Debug.LogWarning(string.Format("Error reading metadata for {0}.\n{1}", + fileInfo.FullPath, SaveLoadScript.m_Instance.LastMetadataError)); + } + LoadSketch(fileInfo, quickload, additive); + if (m_ControlsType != ControlsType.ViewingOnly) + { + EatGazeObjectInput(); + } + } + + public void OpenURLAndInformUser(string url) + { + // On desktop - launch external browser and inform the user + // On mobile - the browser appears over the app + if (!App.Config.IsMobileHardware) + { + OutputWindowScript.m_Instance.CreateInfoCardAtController( + InputManager.ControllerName.Brush, + kRemoveHeadsetFyi, fPopScalar: 0.5f); + } + App.OpenURL(url); + EatGazeObjectInput(); + } + + public bool IsCommandActive(GlobalCommands rEnum, int iParam = -1) + { + switch (rEnum) + { + case GlobalCommands.StraightEdge: return PointerManager.m_Instance.StraightEdgeModeEnabled; + case GlobalCommands.StraightEdgeMeterDisplay: return PointerManager.m_Instance.StraightEdgeGuide.IsShowingMeter(); + case GlobalCommands.SymmetryPlane: return PointerManager.m_Instance.CurrentSymmetryMode == SymmetryMode.SinglePlane; + case GlobalCommands.MultiMirror: return PointerManager.m_Instance.CurrentSymmetryMode == SymmetryMode.MultiMirror; + case GlobalCommands.SymmetryTwoHanded: return PointerManager.m_Instance.CurrentSymmetryMode == SymmetryMode.TwoHanded; + case GlobalCommands.AutoOrient: return m_AutoOrientAfterRotation; + case GlobalCommands.AudioVisualization: return VisualizerManager.m_Instance.VisualsRequested; + case GlobalCommands.AdvancedPanelsToggle: return m_PanelManager.AdvancedModeActive(); + case GlobalCommands.Music: return VisualizerManager.m_Instance.VisualsRequested; + case GlobalCommands.DropCam: return m_DropCam.gameObject.activeSelf; + case GlobalCommands.ToggleAutosimplification: return QualityControls.AutosimplifyEnabled; + case GlobalCommands.DraftingVisibility: return m_DraftingVisibility == (DraftingVisibilityOption)iParam; + case GlobalCommands.Cameras: + return SketchSurfacePanel.m_Instance.GetCurrentToolType() == BaseTool.ToolType.AutoGif || + SketchSurfacePanel.m_Instance.GetCurrentToolType() == BaseTool.ToolType.ScreenshotTool; + case GlobalCommands.IRC: return m_IRCChatWidget != null; + case GlobalCommands.YouTubeChat: return m_YouTubeChatWidget != null; + case GlobalCommands.StencilsDisabled: return m_WidgetManager.StencilsDisabled; + case GlobalCommands.StraightEdgeShape: + // Previously experimental mode only. + // Untested and currently untriggerable. + return PointerManager.m_Instance.StraightEdgeGuide.TempShape == (StraightEdgeGuideScript.Shape)iParam || + (PointerManager.m_Instance.StraightEdgeGuide.TempShape == StraightEdgeGuideScript.Shape.None + && PointerManager.m_Instance.StraightEdgeGuide.CurrentShape == (StraightEdgeGuideScript.Shape)iParam); + case GlobalCommands.Disco: return LightsControlScript.m_Instance.DiscoMode; + case GlobalCommands.ToggleGroupStrokesAndWidgets: return SelectionManager.m_Instance.UngroupingAllowed; + case GlobalCommands.ToggleProfiling: return UnityEngine.Profiling.Profiler.enabled; + case GlobalCommands.ToggleCameraPostEffects: return CameraConfig.PostEffects; + case GlobalCommands.ToggleWatermark: return CameraConfig.Watermark; + case GlobalCommands.ToggleCameraPathVisuals: return m_WidgetManager.CameraPathsVisible; + case GlobalCommands.ToggleCameraPathPreview: return m_WidgetManager.FollowingPath; + case GlobalCommands.SelectCameraPath: + return m_WidgetManager.IsCameraPathAtIndexCurrent(iParam) && + m_WidgetManager.CameraPathsVisible; + case GlobalCommands.GoogleDriveSync_Folder: + return App.DriveSync.IsFolderOfTypeSynced((DriveSync.SyncedFolderType)iParam); + case GlobalCommands.GoogleDriveSync: return App.DriveSync.SyncEnabled; + case GlobalCommands.RecordCameraPath: return VideoRecorderUtils.ActiveVideoRecording != null; + } + return false; + } + + public void NewSketch(bool fade) + { + LightsControlScript.m_Instance.DiscoMode = false; + m_WidgetManager.FollowingPath = false; + SketchMemoryScript.m_Instance.ClearMemory(); + ControllerConsoleScript.m_Instance.AddNewLine("Sketch Cleared"); + ResetGrabbedPose(everything: true); + QualityControls.m_Instance.ResetAutoQuality(); + InputManager.m_Instance.TriggerHaptics(InputManager.ControllerName.Brush, 0.1f); + SaveLoadScript.m_Instance.ResetLastFilename(); + SelectionManager.m_Instance.RemoveFromSelection(false); + PointerManager.m_Instance.ResetSymmetryToHome(); + App.Scene.ResetLayers(notify: true); + ApiManager.Instance.ResetBrushTransform(); + + // If we've got the camera path tool active, switch back to the default tool. + // I'm doing this because if we leave the camera path tool active, the camera path + // panel shows the button highlighted, which affects the user's flow for being + // invited to start a path. It looks weird. + if (m_SketchSurfacePanel.ActiveToolType == BaseTool.ToolType.CameraPathTool) + { + m_SketchSurfacePanel.EnableDefaultTool(); + } + + m_WidgetManager.DestroyAllWidgets(); + if (LightsControlScript.m_Instance.LightsChanged || + SceneSettings.m_Instance.EnvironmentChanged) + { + SceneSettings.m_Instance.RecordSkyColorsForFading(); + SceneSettings.m_Instance.SetDesiredPreset( + SceneSettings.m_Instance.GetDesiredPreset(), skipFade: !fade); + } + // Blank the thumbnail position so that autosave won't save the thumbnail position to be + // the one from the old sketch. + SaveLoadScript.m_Instance.LastThumbnail_SS = null; + + // Re-set the quality level to reset simplification level + QualityControls.m_Instance.QualityLevel = QualityControls.m_Instance.QualityLevel; + + App.IcosaAssetCatalog.ClearLoadingQueue(); + App.IcosaAssetCatalog.UnloadUnusedModels(); + } + + private bool WorldIsReset(bool toSavedXf) + { + return App.Scene.Pose == + (toSavedXf ? SketchMemoryScript.m_Instance.InitialSketchTransform : TrTransform.identity); + } + + public bool IsCommandAvailable(GlobalCommands rEnum, int iParam = -1) + { + // TODO: hide gallery view / publish if there are no saved sketches + switch (rEnum) + { + case GlobalCommands.Undo: return SketchMemoryScript.m_Instance.CanUndo(); + case GlobalCommands.Redo: return SketchMemoryScript.m_Instance.CanRedo(); + case GlobalCommands.Save: + bool canSave = + SaveLoadScript.m_Instance.SceneFile.Valid && + SaveLoadScript.m_Instance.IsSavingAllowed(); + return canSave && (!WorldIsReset(toSavedXf: true) || + (SketchHasChanges() && SketchMemoryScript.m_Instance.IsMemoryDirty())); + case GlobalCommands.SaveOptions: + case GlobalCommands.SaveNew: + case GlobalCommands.SaveGallery: + return SketchHasChanges(); + case GlobalCommands.SaveOnLocalChanges: + if (!SaveLoadScript.m_Instance.SceneFile.Valid) + { + // No save file, but something has changed. + return SketchHasChanges(); + } + else + { + if (SaveLoadScript.m_Instance.CanOverwriteSource) + { + // Save file, and it's our file. Whether we have changes is irrelevant. + return true; + } + // Save file, but it's not our file. Only make a copy if there are local changes. + return SketchMemoryScript.m_Instance.IsMemoryDirty(); + } + case GlobalCommands.UploadToGenericCloud: + return SketchMemoryScript.m_Instance.HasVisibleObjects() || + m_WidgetManager.ExportableModelWidgets.Any(w => w.gameObject.activeSelf) || + m_WidgetManager.ImageWidgets.Any(w => w.gameObject.activeSelf) || + VrAssetService.m_Instance.UploadProgress >= 1.0f || + VrAssetService.m_Instance.LastUploadFailed; + case GlobalCommands.SaveAndUpload: + return App.GoogleIdentity.LoggedIn && + (VrAssetService.m_Instance.UploadProgress <= 0.0f) && + IsCommandAvailable(GlobalCommands.UploadToGenericCloud); + case GlobalCommands.NewSketch: + return SketchHasChanges(); + case GlobalCommands.Credits: + case GlobalCommands.AshleysSketch: + return !SketchHasChanges() && !SketchMemoryScript.m_Instance.IsMemoryDirty(); + case GlobalCommands.Tiltasaurus: return TiltBrush.Tiltasaurus.m_Instance.TiltasaurusAvailable(); + case GlobalCommands.ExportRaw: + return SketchMemoryScript.m_Instance.HasVisibleObjects() || + m_WidgetManager.ModelWidgets.Any(w => w.gameObject.activeSelf) || + m_WidgetManager.ImageWidgets.Any(w => w.gameObject.activeSelf); + case GlobalCommands.ResetAllPanels: return m_PanelManager.PanelsHaveBeenCustomized(); + case GlobalCommands.Duplicate: return ClipboardManager.Instance.CanCopy; + case GlobalCommands.ToggleGroupStrokesAndWidgets: return SelectionManager.m_Instance.SelectionCanBeGrouped; + case GlobalCommands.SaveModel: return SelectionManager.m_Instance.HasSelection; + case GlobalCommands.SummonMirror: + return PointerManager.m_Instance.CurrentSymmetryMode != + SymmetryMode.None; + case GlobalCommands.InvertSelection: + case GlobalCommands.FlipSelection: + return SelectionManager.m_Instance.HasSelection; + case GlobalCommands.SelectAll: + return SketchMemoryScript.m_Instance.HasVisibleObjects() || + m_WidgetManager.HasSelectableWidgets(); + case GlobalCommands.UnloadReferenceImageCatalog: + return ReferenceImageCatalog.m_Instance.AnyImageValid(); + case GlobalCommands.ToggleCameraPathPreview: + return m_WidgetManager.CanRecordCurrentCameraPath(); + case GlobalCommands.DeleteCameraPath: + return CameraPathCaptureRig.Enabled && m_WidgetManager.AnyActivePathHasAKnot(); + case GlobalCommands.ToggleCameraPathVisuals: + return m_WidgetManager.AnyActivePathHasAKnot(); + case GlobalCommands.GoogleDriveSync: + return App.GoogleIdentity.LoggedIn; + case GlobalCommands.RecordCameraPath: return m_WidgetManager.CameraPathsVisible; + } + return true; + } + + public bool SketchHasChanges() + { + if (SceneSettings.m_Instance.IsTransitioning) { return false; } + return SketchMemoryScript.m_Instance.HasVisibleObjects() || + SceneSettings.m_Instance.EnvironmentChanged || + LightsControlScript.m_Instance.LightsChanged || + m_WidgetManager.ModelWidgets.Any(w => w.gameObject.activeSelf) || + m_WidgetManager.LightWidgets.Any(w => w.gameObject.activeSelf) || + m_WidgetManager.StencilWidgets.Any(w => w.gameObject.activeSelf) || + m_WidgetManager.ImageWidgets.Any(w => w.gameObject.activeSelf) || + m_WidgetManager.VideoWidgets.Any(w => w.gameObject.activeSelf) || + m_WidgetManager.AnyCameraPathWidgetsActive; + } + + public void OpenPanelOfType(BasePanel.PanelType type, TrTransform trSpawnXf) + { + m_PanelManager.OpenPanel(type, trSpawnXf); + EatGazeObjectInput(); + } + + public void RestoreFloatingPanels() + { + if (!m_SketchSurfacePanel.ActiveTool.HidePanels()) + { + m_PanelManager.RestoreHiddenPanels(); + } + } + + public void UpdateDraftingVisibility() + { + float value = 0; + switch (m_DraftingVisibility) + { + case DraftingVisibilityOption.Visible: + value = 1; + break; + case DraftingVisibilityOption.Transparent: + value = .5f; + break; + case DraftingVisibilityOption.Hidden: + value = 0; + break; + } + Shader.SetGlobalFloat("_DraftingVisibility01", value); + } + + private void ToggleProfiling() + { + if (Debug.isDebugBuild && ProfileDisplay.Instance != null) + { + ProfileDisplay.Instance.gameObject.SetActive(UnityEngine.Profiling.Profiler.enabled); + } + if (UnityEngine.Profiling.Profiler.enabled) + { + ProfilingManager.Instance.StopProfiling(); + } + else + { + ProfilingManager.Instance.StartProfiling(App.UserConfig.Profiling.ProfilingMode); + } + } + + private void DoAutoProfile() + { + StartCoroutine(DoProfiling()); + } + + private void DoAutoProfileAndQuit() + { + StartCoroutine(DoProfiling(andQuit: true)); + } + + private IEnumerator DoProfiling(bool andQuit = false) + { + TrTransform oldWandPose = TrTransform.FromTransform(InputManager.Wand.Geometry.transform); + TrTransform oldBrushPose = TrTransform.FromTransform(InputManager.Brush.Geometry.transform); + + App.AppState oldState = App.CurrentState; + App.Instance.SetDesiredState(App.AppState.AutoProfiling); + while (App.CurrentState != App.AppState.AutoProfiling) + { + yield return null; + } + + TrTransform camPose = App.Scene.Pose * SaveLoadScript.m_Instance.ReasonableThumbnail_SS; + camPose.ToTransform(App.VrSdk.GetVrCamera().transform); + float controllerDirection = App.UserConfig.Profiling.ShowControllers ? 1f : -1f; + Vector3 roffset = Camera.main.transform.right * 2f; + Vector3 fOffset = Camera.main.transform.forward * 4f * controllerDirection; + InputManager.Brush.Geometry.transform.position = Camera.main.transform.position + roffset + fOffset; + InputManager.Brush.Geometry.transform.rotation = Camera.main.transform.rotation; + InputManager.Wand.Geometry.transform.position = Camera.main.transform.position - roffset + fOffset; + InputManager.Wand.Geometry.transform.rotation = Camera.main.transform.rotation; + m_PanelManager.LockPanelsToController(); + + ProfilingManager.Instance.StartProfiling(App.UserConfig.Profiling.ProfilingMode); + yield return new WaitForSeconds(App.UserConfig.Profiling.Duration); + ProfilingManager.Instance.StopProfiling(); + + if (App.UserConfig.Profiling.TakeScreenshot) + { + GameObject camObj = new GameObject("ScreenShotter"); + Camera cam = camObj.AddComponent(); + cam.CopyFrom(App.VrSdk.GetVrCamera()); + cam.stereoTargetEye = StereoTargetEyeMask.None; + cam.clearFlags = CameraClearFlags.SolidColor; + camPose.ToTransform(camObj.transform); + int res = App.UserConfig.Profiling.ScreenshotResolution; + RenderTexture renderTexture = RenderTexture.GetTemporary(res, res, 24); + try + { + cam.targetTexture = renderTexture; + cam.Render(); + RenderTexture prev = RenderTexture.active; + RenderTexture.active = renderTexture; + var texture = new Texture2D(res, res, TextureFormat.RGB24, false); + texture.ReadPixels(new Rect(0, 0, texture.width, texture.height), 0, 0); + RenderTexture.active = prev; + byte[] jpegBytes = texture.EncodeToJPG(); + string filename = + Path.GetFileNameWithoutExtension(SaveLoadScript.m_Instance.SceneFile.FullPath); + File.WriteAllBytes(Path.Combine(App.UserPath(), filename + ".jpg"), jpegBytes); + } + finally + { + Destroy(camObj); + RenderTexture.ReleaseTemporary(renderTexture); + } + } + + oldWandPose.ToTransform(InputManager.Wand.Geometry.transform); + oldBrushPose.ToTransform(InputManager.Brush.Geometry.transform); + App.Instance.SetDesiredState(oldState); + + if (andQuit) + { + QuitApp(); + } + } + } + +} // namespace TiltBrush diff --git a/Assets/Scripts/UserConfig.cs b/Assets/Scripts/UserConfig.cs index 313c82fdc6..0f4dda1b6d 100644 --- a/Assets/Scripts/UserConfig.cs +++ b/Assets/Scripts/UserConfig.cs @@ -1,683 +1,702 @@ -// Copyright 2020 The Tilt Brush Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// 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 Newtonsoft.Json; - -namespace TiltBrush -{ - - // Use "struct" instead of "class" to prohibit the use of default values, - // which won't work the way you want. Use Nullable<> instead. - [Serializable] - public class UserConfig - { - [Serializable] - public struct YouTubeConfig - { - public string ChannelID; - } - public YouTubeConfig YouTube; - - [Serializable] - public struct FlagsConfig - { - public bool DisableAudio; - public bool DisableAutosave; - public bool DisablePoly; - public bool UnlockScale; - public bool GuideToggleVisiblityOnly; - public bool HighResolutionSnapshots; // Deprecated - public bool ShowDroppedFrames; - public bool LargeMeshSupport; - public bool EnableMonoscopicMode; - - private bool? m_DisableXrMode; - public bool DisableXrMode - { - get - { -#if UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX - return true; -#else - return m_DisableXrMode ?? false; -#endif - } - set { m_DisableXrMode = value; } - } - - public bool EnableApiRemoteCalls; - public bool EnableApiCorsHeaders; - - bool? m_AdvancedKeyboardShortcuts; - public bool AdvancedKeyboardShortcuts - { - get - { - return m_AdvancedKeyboardShortcuts ?? false; - } - set { m_AdvancedKeyboardShortcuts = value; } - } - - bool? m_PostEffectsOnCapture; - public bool PostEffectsOnCaptureValid { get { return m_PostEffectsOnCapture != null; } } - public bool PostEffectsOnCapture - { - get { return m_PostEffectsOnCapture ?? true; } - set { m_PostEffectsOnCapture = value; } - } - - // Spectator-cam watermark doesn't update on the fly - // The snapshot/video watermark does, though - bool? m_ShowWatermark; - public bool ShowWatermarkValid { get { return m_ShowWatermark != null; } } - public bool ShowWatermark - { - get { return m_ShowWatermark ?? true; } - set { m_ShowWatermark = value; } - } - - // This doesn't update on the fly - bool? m_ShowHeadset; - public bool ShowHeadset - { - get { return m_ShowHeadset ?? true; } - set { m_ShowHeadset = value; } - } - - // This doesn't update on the fly - bool? m_ShowControllers; - public bool ShowControllers - { - get { return m_ShowControllers ?? true; } - set { m_ShowControllers = value; } - } - - bool? m_SkipIntro; - public bool SkipIntro - { - get { return m_SkipIntro ?? false; } - set { m_SkipIntro = value; } - } - - int? m_SnapshotHeight; - public int SnapshotHeight - { - get { return m_SnapshotHeight ?? -1; } - set - { - int max = App.Config.PlatformConfig.MaxSnapshotDimension; - if (value > max) - { - OutputWindowScript.Error( - $"Snapshot height of {value} is not supported. Set to {max} pixels."); - m_SnapshotHeight = max; - } - else - { - m_SnapshotHeight = value; - } - } - } - - int? m_SnapshotWidth; - public int SnapshotWidth - { - get { return m_SnapshotWidth ?? -1; } - set - { - int max = App.Config.PlatformConfig.MaxSnapshotDimension; - if (value > max) - { - OutputWindowScript.Error( - $"Snapshot width of {value} is not supported. Set to {max} pixels."); - m_SnapshotWidth = max; - } - else - { - m_SnapshotWidth = value; - } - } - } - - float? m_Fov; - public bool FovValid { get { return m_Fov != null; } } - public float Fov - { - get { return m_Fov ?? CameraConfig.kFovDefault; } - set - { - m_Fov = UnityEngine.Mathf.Clamp(value, CameraConfig.kFovMin, CameraConfig.kFovMax); - if (m_Fov != value) - { - OutputWindowScript.Error(string.Format("FOV of '{0}' not supported.", value), - string.Format("FOV must be between {0} and {1}.\nFOV set to {2}.", - CameraConfig.kFovMin, CameraConfig.kFovMax, m_Fov)); - } - } - } - - private bool? m_PolyModelPreload; - public bool PolyModelPreloadValid => m_PolyModelPreload.HasValue; - public bool PolyModelPreload - { - get - { - return m_PolyModelPreload ?? App.PlatformConfig.EnablePolyPreload; - } - set { m_PolyModelPreload = value; } - } - } - - public FlagsConfig Flags; - - [Serializable] - public struct DemoConfig - { - public bool Enabled; - public uint? Duration; - public bool PublishAutomatically; - - private string m_PublishTitle; - public string PublishTitle - { - get { return m_PublishTitle ?? $"Sketch from {App.kAppDisplayName} demo"; } - set { m_PublishTitle = value; } - } - - private string m_PublishDescription; - public string PublishDescription - { - get { return m_PublishDescription ?? ""; } - set { m_PublishDescription = value; } - } - } - public DemoConfig Demo; - - [Serializable] - public struct BrushConfig - { - private Dictionary m_AddTagsToBrushes; - private Dictionary m_RemoveTagsFromBrushes; - private string[] m_IncludeTags; - private string[] m_ExcludeTags; - - public Dictionary AddTagsToBrushes - { - get => m_AddTagsToBrushes ?? (m_AddTagsToBrushes = new Dictionary()); - set => m_AddTagsToBrushes = value; - } - - public Dictionary RemoveTagsFromBrushes - { - get => m_RemoveTagsFromBrushes ?? (m_RemoveTagsFromBrushes = new Dictionary()); - set => m_RemoveTagsFromBrushes = value; - } - - public string[] IncludeTags - { - get - { - if (m_IncludeTags == null) - { - if (App.Config.GetIsExperimental()) - { - m_IncludeTags = new[] { "default", "experimental" }; - } - else - { - m_IncludeTags = new[] { "default" }; - } - } - return m_IncludeTags; - } - set => m_IncludeTags = value; - } - - public string[] ExcludeTags - { - get => m_ExcludeTags ?? (ExcludeTags = Array.Empty()); - set => m_ExcludeTags = value; - } - } - public BrushConfig Brushes; - - [Serializable] - public struct ImportConfig - { - bool? m_UseUnityGltf; - public bool UseUnityGltf - { - get { return m_UseUnityGltf ?? false; } - set { m_UseUnityGltf = value; } - } - } - - [Serializable] - public struct ExportConfig - { - bool? m_ExportBinaryFbx; - public bool ExportBinaryFbx - { - get { return m_ExportBinaryFbx ?? true; } - set { m_ExportBinaryFbx = value; } - } - - string m_ExportFbxVersion; - public string ExportFbxVersion - { - get { return m_ExportFbxVersion ?? "FBX201400"; } - set { m_ExportFbxVersion = value; } - } - - bool? m_ExportStrokeTimestamp; - public bool ExportStrokeTimestamp - { - get { return m_ExportStrokeTimestamp ?? true; } - set { m_ExportStrokeTimestamp = value; } - } - - bool? m_ExportStrokeMetadata; - public bool ExportStrokeMetadata - { - get { return m_ExportStrokeMetadata ?? false; } - set { m_ExportStrokeMetadata = value; } - } - - bool? m_KeepStrokes; - public bool KeepStrokes - { - get { return m_KeepStrokes ?? false; } - set { m_KeepStrokes = value; } - } - - bool? m_KeepGroups; - public bool KeepGroups - { - get { return m_KeepGroups ?? true; } - set { m_KeepGroups = value; } - } - - private Dictionary m_Formats; - [JsonProperty] - public Dictionary Formats - { - get { return m_Formats ?? null; } - set => m_Formats = value; - } - } - - public ImportConfig Import; - public ExportConfig Export; - - [Serializable] - public struct SharingConfig - { - // For Poly testing allow us to use a different API host and landing page URL. - [JsonProperty("VrAssetServiceHost")] public string VrAssetServiceHostOverride; - [JsonProperty("VrAssetServiceUrl")] public string VrAssetServiceUrlOverride; - } - public SharingConfig Sharing; - - [Serializable] - public struct IdentityConfig - { - public string Author; - } - public IdentityConfig User; - - [Serializable] - public struct VideoConfig - { - // Default values and limits. - private const float kDefaultFps = 30f; - private const float kDefaultOfflineFps = 60f; - private const float kMinFps = 1f; - private const float kMaxFps = 60f; - private const float kMaxOfflineFps = 1000f; - private const int kDefaultRes = 1280; - private const int kDefaultOfflineRes = 1920; - private const int kMinRes = 640; - private const int kMaxRes = 2560; - private const int kMaxOfflineRes = 8000; - private const string kDefaultContainer = "mp4"; - private static readonly List kSupportedContainers = new List - { - "mp4", "mov", "avi", "mpeg", "ogv", "ogx", - }; - - private const string kDefaultVideoEncoder = "h.264"; - private static readonly List kSupportedVideoEncoders = new List - { - "h.264", "h.265", - }; - - private const float kDefaultSmoothing = 0.98f; - private const float kDefaultOdsPoleCollapsing = 1.0f; - - float? m_FPS; - public float FPS - { - get { return m_FPS ?? kDefaultFps; } - set - { - m_FPS = UnityEngine.Mathf.Clamp(value, kMinFps, kMaxFps); - if (m_FPS != value) - { - OutputWindowScript.Error(string.Format("Video FPS of '{0}' not supported.", value), - string.Format("FPS must be between {0} and {1}.\nFPS set to {2}.", - UnityEngine.Mathf.RoundToInt(kMinFps), - UnityEngine.Mathf.RoundToInt(kMaxFps), m_FPS)); - } - } - } - - float? m_OfflineFps; - public float OfflineFPS - { - get { return m_OfflineFps ?? kDefaultOfflineFps; } - set - { - m_OfflineFps = UnityEngine.Mathf.Clamp(value, kMinFps, kMaxOfflineFps); - if (OfflineFPS != value) - { - OutputWindowScript.Error(string.Format("Offline Video FPS of '{0}' not supported.", value), - string.Format("FPS must be between {0} and {1}.\nFPS set to {2}.", - UnityEngine.Mathf.RoundToInt(kMinFps), - UnityEngine.Mathf.RoundToInt(kMaxOfflineFps), OfflineFPS)); - } - } - } - - float? m_Fov; - public bool FovValid { get { return m_Fov != null; } } - public float Fov - { - get { return m_Fov ?? CameraConfig.kFovDefault; } - set - { - m_Fov = UnityEngine.Mathf.Clamp(value, CameraConfig.kFovMin, CameraConfig.kFovMax); - if (m_Fov != value) - { - OutputWindowScript.Error(string.Format("FOV of '{0}' not supported.", value), - string.Format("FOV must be between {0} and {1}.\nFOV set to {2}.", - CameraConfig.kFovMin, CameraConfig.kFovMax, m_Fov)); - } - } - } - - int? m_Resolution; - public int Resolution - { - get { return m_Resolution ?? kDefaultRes; } - set - { - m_Resolution = UnityEngine.Mathf.Clamp(value, kMinRes, kMaxRes); - if (m_Resolution != value) - { - OutputWindowScript.Error(string.Format("Video Resolution of '{0}' not supported.", value), - string.Format("Resolution must be between {0} and {1}.\nResolution set to {2}.", - kMinRes, kMaxRes, m_Resolution)); - } - } - } - - int? m_OfflineResolution; - public int OfflineResolution - { - get { return m_OfflineResolution ?? kDefaultOfflineRes; } - set - { - m_OfflineResolution = UnityEngine.Mathf.Clamp(value, 640, kMaxOfflineRes); - if (m_OfflineResolution != value) - { - OutputWindowScript.Error(string.Format("Video Resolution of '{0}' not supported.", value), - string.Format("Resolution must be between {0} and {1}.\nResolution set to {2}.", - kMinRes, kMaxOfflineRes, m_OfflineResolution)); - } - } - } - - private bool? m_SaveCameraPath; - public bool SaveCameraPath - { - get { return m_SaveCameraPath ?? true; } - set - { - m_SaveCameraPath = value; - } - } - - string m_VideoEncoder; - public string Encoder - { - get { return m_VideoEncoder ?? kDefaultVideoEncoder; } - set - { - string lowered = value.ToLowerInvariant(); - if (kSupportedVideoEncoders.Contains(lowered)) - { - m_VideoEncoder = lowered; - } - else - { - m_VideoEncoder = null; - OutputWindowScript.Error( - $"VideoEncoder '{lowered}' not supported in {App.kConfigFileName}", - string.Format("Supported: {0}.\nContainer type set to {1}.", - string.Join(", ", kSupportedVideoEncoders.ToArray()), - kDefaultVideoEncoder)); - } - } - } - - string m_ContainerType; - public string ContainerType - { - get { return m_ContainerType ?? kDefaultContainer; } - set - { - string lowered = value.ToLowerInvariant(); - if (kSupportedContainers.Contains(lowered)) - { - m_ContainerType = lowered; - } - else - { - m_ContainerType = null; - OutputWindowScript.Error( - $"ContainerType '{lowered}' not supported in {App.kConfigFileName}", - string.Format("Supported: {0}.\nContainer type set to {1}.", - string.Join(", ", kSupportedContainers.ToArray()), kDefaultContainer)); - } - } - } - - float? m_CameraSmoothing; - public bool CameraSmoothingValid { get { return m_CameraSmoothing != null; } } - public float CameraSmoothing - { - get { return m_CameraSmoothing ?? kDefaultSmoothing; } - set - { - m_CameraSmoothing = UnityEngine.Mathf.Clamp01(value); - if (m_CameraSmoothing != value) - { - OutputWindowScript.Error(string.Format("Camera smoothing of '{0}' not supported.", value), - string.Format("Smoothing must be between 0 and 1.\nSmoothing set to {0}.", - m_CameraSmoothing)); - } - } - } - - float? m_OdsPoleCollapsing; - public float OdsPoleCollapsing - { - get { return m_OdsPoleCollapsing ?? kDefaultOdsPoleCollapsing; } - set - { - m_OdsPoleCollapsing = UnityEngine.Mathf.Clamp01(value); - if (m_OdsPoleCollapsing != value) - { - OutputWindowScript.Error(string.Format("Pole Collapsing of '{0}' not supported.", value), - string.Format("Smoothing must be between 0 and 1.\nPole Collapsing set to {0}.", - m_OdsPoleCollapsing)); - } - } - } - } - - public VideoConfig Video; - - // Settings for the QA testing panel. - [Serializable] - public struct TestingConfig - { - public Dictionary BrushReplacementMap - { - get - { - Dictionary results = new Dictionary(); - if (Config.IsExperimental) - { - if (string.IsNullOrEmpty(BrushReplacements)) - { - return results; - } - var replacements = BrushReplacements.Split(','); - foreach (string replacement in replacements) - { - string[] pair = replacement.Split('='); - if (pair.Length == 2) - { - if (pair[0] == "*") - { - Guid guid = new Guid(pair[1]); - foreach (var brush in App.Instance.m_Manifest.Brushes) - { - results.Add(brush.m_Guid, guid); - } - } - else - { - results.Add(new Guid(pair[0]), new Guid(pair[1])); - } - } - else - { - OutputWindowScript.Error("BrushReplacement should be of the form:\n" + - "brushguidA=brushguidB,brushguidC=brushguidD"); - } - } - } - return results; - } - } - - public bool Enabled; - public string InputFile; - public string OutputFile; - public bool ResetPromos; - public bool FirstRun; - public string BrushReplacements; - } - public TestingConfig Testing; - - // Profiling Settings - [Serializable] - public struct ProfilingConfig - { - public const int kDefaultScreenshotResolution = 1000; - public string[] ProfilingFunctions { get; private set; } - public ProfilingManager.Mode ProfilingMode { get; private set; } - - public string Mode - { - set - { - try - { - ProfilingMode = (ProfilingManager.Mode)Enum.Parse(typeof(ProfilingManager.Mode), value); - } - catch (ArgumentException) - { - OutputWindowScript.Error(string.Format("'{0}' is not a valid profiling mode.", value)); - } - } - } - - public string Functions - { - set { ProfilingFunctions = value.Split(','); } - } - - public string ProfileName; - public string ProfileFilename; - public string SketchToLoad; - public bool AutoProfile; - public bool ShowControllers; - - public float Duration - { - get { return m_Duration.HasValue ? m_Duration.Value : 5f; } - set { m_Duration = value; } - } - private float? m_Duration; - - public bool Csv; - - // Any invalid quality level is ignored. - private int? m_QualityLevel; - public int QualityLevel - { - get { return m_QualityLevel.HasValue ? m_QualityLevel.Value : -1; } - set { m_QualityLevel = value; } - } - - public float ViewportScaling { get; set; } - public float EyeTextureScaling { get; set; } - public int GlobalMaximumLOD { get; set; } - public int MsaaLevel { get; set; } - public bool TakeScreenshot { get; set; } - private int? m_screenshotResolution; - - public int ScreenshotResolution - { - get - { - return m_screenshotResolution.HasValue ? - m_screenshotResolution.Value : kDefaultScreenshotResolution; - } - set { m_screenshotResolution = value; } - } - public bool PerfgateOutput { get; set; } - - private float? m_StrokeSimplification; - - public float StrokeSimplification - { - get { return m_StrokeSimplification.HasValue ? m_StrokeSimplification.Value : 0f; } - set { m_StrokeSimplification = value; } - } - - public bool HasStrokeSimplification - { - get { return m_StrokeSimplification.HasValue; } - } - } - public ProfilingConfig Profiling; - } - -} // namespace TiltBrush +// Copyright 2020 The Tilt Brush Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// 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 Newtonsoft.Json; +using UnityEngine.Serialization; + +namespace TiltBrush +{ + + // Use "struct" instead of "class" to prohibit the use of default values, + // which won't work the way you want. Use Nullable<> instead. + [Serializable] + public class UserConfig + { + [Serializable] + public struct YouTubeConfig + { + public string ChannelID; + } + public YouTubeConfig YouTube; + + [Serializable] + public struct FlagsConfig + { + public bool DisableAudio; + public bool DisableAutosave; + [FormerlySerializedAs("DisablePoly")] public bool DisableIcosa; + public bool UnlockScale; + public bool GuideToggleVisiblityOnly; + public bool HighResolutionSnapshots; // Deprecated + public bool ShowDroppedFrames; + public bool LargeMeshSupport; + public bool EnableMonoscopicMode; + + private bool? m_DisableXrMode; + public bool DisableXrMode + { + get + { +#if UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX + return true; +#else + return m_DisableXrMode ?? false; +#endif + } + set { m_DisableXrMode = value; } + } + + public bool EnableApiRemoteCalls; + public bool EnableApiCorsHeaders; + + bool? m_AdvancedKeyboardShortcuts; + public bool AdvancedKeyboardShortcuts + { + get + { + return m_AdvancedKeyboardShortcuts ?? false; + } + set { m_AdvancedKeyboardShortcuts = value; } + } + + bool? m_PostEffectsOnCapture; + public bool PostEffectsOnCaptureValid { get { return m_PostEffectsOnCapture != null; } } + public bool PostEffectsOnCapture + { + get { return m_PostEffectsOnCapture ?? true; } + set { m_PostEffectsOnCapture = value; } + } + + // Spectator-cam watermark doesn't update on the fly + // The snapshot/video watermark does, though + bool? m_ShowWatermark; + public bool ShowWatermarkValid { get { return m_ShowWatermark != null; } } + public bool ShowWatermark + { + get { return m_ShowWatermark ?? true; } + set { m_ShowWatermark = value; } + } + + // This doesn't update on the fly + bool? m_ShowHeadset; + public bool ShowHeadset + { + get { return m_ShowHeadset ?? true; } + set { m_ShowHeadset = value; } + } + + // This doesn't update on the fly + bool? m_ShowControllers; + public bool ShowControllers + { + get { return m_ShowControllers ?? true; } + set { m_ShowControllers = value; } + } + + bool? m_SkipIntro; + public bool SkipIntro + { + get { return m_SkipIntro ?? false; } + set { m_SkipIntro = value; } + } + + int? m_SnapshotHeight; + public int SnapshotHeight + { + get { return m_SnapshotHeight ?? -1; } + set + { + int max = App.Config.PlatformConfig.MaxSnapshotDimension; + if (value > max) + { + OutputWindowScript.Error( + $"Snapshot height of {value} is not supported. Set to {max} pixels."); + m_SnapshotHeight = max; + } + else + { + m_SnapshotHeight = value; + } + } + } + + int? m_SnapshotWidth; + public int SnapshotWidth + { + get { return m_SnapshotWidth ?? -1; } + set + { + int max = App.Config.PlatformConfig.MaxSnapshotDimension; + if (value > max) + { + OutputWindowScript.Error( + $"Snapshot width of {value} is not supported. Set to {max} pixels."); + m_SnapshotWidth = max; + } + else + { + m_SnapshotWidth = value; + } + } + } + + float? m_Fov; + public bool FovValid { get { return m_Fov != null; } } + public float Fov + { + get { return m_Fov ?? CameraConfig.kFovDefault; } + set + { + m_Fov = UnityEngine.Mathf.Clamp(value, CameraConfig.kFovMin, CameraConfig.kFovMax); + if (m_Fov != value) + { + OutputWindowScript.Error(string.Format("FOV of '{0}' not supported.", value), + string.Format("FOV must be between {0} and {1}.\nFOV set to {2}.", + CameraConfig.kFovMin, CameraConfig.kFovMax, m_Fov)); + } + } + } + + private bool? m_IcosaModelPreload; + public bool PolyModelPreloadValid => m_IcosaModelPreload.HasValue; + public bool IcosaModelPreload + { + get + { + return m_IcosaModelPreload ?? App.PlatformConfig.EnablePolyPreload; + } + set { m_IcosaModelPreload = value; } + } + } + + public FlagsConfig Flags; + + [Serializable] + public struct DemoConfig + { + public bool Enabled; + public uint? Duration; + public bool PublishAutomatically; + + private string m_PublishTitle; + public string PublishTitle + { + get { return m_PublishTitle ?? $"Sketch from {App.kAppDisplayName} demo"; } + set { m_PublishTitle = value; } + } + + private string m_PublishDescription; + public string PublishDescription + { + get { return m_PublishDescription ?? ""; } + set { m_PublishDescription = value; } + } + } + public DemoConfig Demo; + + [Serializable] + public struct BrushConfig + { + private Dictionary m_AddTagsToBrushes; + private Dictionary m_RemoveTagsFromBrushes; + private string[] m_IncludeTags; + private string[] m_ExcludeTags; + + public Dictionary AddTagsToBrushes + { + get => m_AddTagsToBrushes ?? (m_AddTagsToBrushes = new Dictionary()); + set => m_AddTagsToBrushes = value; + } + + public Dictionary RemoveTagsFromBrushes + { + get => m_RemoveTagsFromBrushes ?? (m_RemoveTagsFromBrushes = new Dictionary()); + set => m_RemoveTagsFromBrushes = value; + } + + public string[] IncludeTags + { + get + { + if (m_IncludeTags == null) + { + if (App.Config.GetIsExperimental()) + { + m_IncludeTags = new[] { "default", "experimental" }; + } + else + { + m_IncludeTags = new[] { "default" }; + } + } + return m_IncludeTags; + } + set => m_IncludeTags = value; + } + + public string[] ExcludeTags + { + get => m_ExcludeTags ?? (ExcludeTags = Array.Empty()); + set => m_ExcludeTags = value; + } + } + public BrushConfig Brushes; + + [Serializable] + public struct ImportConfig + { + bool? m_UseUnityGltf; + public bool UseUnityGltf + { + get { return m_UseUnityGltf ?? false; } + set { m_UseUnityGltf = value; } + } + } + + [Serializable] + public struct ExportConfig + { + bool? m_ExportBinaryFbx; + public bool ExportBinaryFbx + { + get { return m_ExportBinaryFbx ?? true; } + set { m_ExportBinaryFbx = value; } + } + + string m_ExportFbxVersion; + public string ExportFbxVersion + { + get { return m_ExportFbxVersion ?? "FBX201400"; } + set { m_ExportFbxVersion = value; } + } + + bool? m_ExportStrokeTimestamp; + public bool ExportStrokeTimestamp + { + get { return m_ExportStrokeTimestamp ?? true; } + set { m_ExportStrokeTimestamp = value; } + } + + // Used by UnityGLTF exporter + bool? m_ExportStrokeMetadata; + public bool ExportStrokeMetadata + { + get { return m_ExportStrokeMetadata ?? false; } + set { m_ExportStrokeMetadata = value; } + } + + // Used by UnityGLTF exporter + bool? m_KeepStrokes; + public bool KeepStrokes + { + get { return m_KeepStrokes ?? false; } + set { m_KeepStrokes = value; } + } + + // Used by UnityGLTF exporter + bool? m_KeepGroups; + public bool KeepGroups + { + get { return m_KeepGroups ?? true; } + set { m_KeepGroups = value; } + } + + // Used by UnityGLTF exporter + private bool? m_ExportEnvironment; + public bool ExportEnvironment + { + get { return m_ExportEnvironment ?? false; } + set { m_ExportEnvironment = value; } + } + + // Used by UnityGLTF exporter + private bool? m_ExportCustomSkybox; + public bool ExportCustomSkybox + { + get { return m_ExportCustomSkybox ?? false; } + set { m_ExportCustomSkybox = value; } + } + + private Dictionary m_Formats; + [JsonProperty] + public Dictionary Formats + { + get { return m_Formats ?? null; } + set => m_Formats = value; + } + } + + public ImportConfig Import; + public ExportConfig Export; + + [Serializable] + public struct SharingConfig + { + public string IcosaApiRoot; + public string IcosaHomePage; + } + public SharingConfig Sharing; + + [Serializable] + public struct IdentityConfig + { + public string Author; + } + public IdentityConfig User; + + [Serializable] + public struct VideoConfig + { + // Default values and limits. + private const float kDefaultFps = 30f; + private const float kDefaultOfflineFps = 60f; + private const float kMinFps = 1f; + private const float kMaxFps = 60f; + private const float kMaxOfflineFps = 1000f; + private const int kDefaultRes = 1280; + private const int kDefaultOfflineRes = 1920; + private const int kMinRes = 640; + private const int kMaxRes = 2560; + private const int kMaxOfflineRes = 8000; + private const string kDefaultContainer = "mp4"; + private static readonly List kSupportedContainers = new List + { + "mp4", "mov", "avi", "mpeg", "ogv", "ogx", + }; + + private const string kDefaultVideoEncoder = "h.264"; + private static readonly List kSupportedVideoEncoders = new List + { + "h.264", "h.265", + }; + + private const float kDefaultSmoothing = 0.98f; + private const float kDefaultOdsPoleCollapsing = 1.0f; + + float? m_FPS; + public float FPS + { + get { return m_FPS ?? kDefaultFps; } + set + { + m_FPS = UnityEngine.Mathf.Clamp(value, kMinFps, kMaxFps); + if (m_FPS != value) + { + OutputWindowScript.Error(string.Format("Video FPS of '{0}' not supported.", value), + string.Format("FPS must be between {0} and {1}.\nFPS set to {2}.", + UnityEngine.Mathf.RoundToInt(kMinFps), + UnityEngine.Mathf.RoundToInt(kMaxFps), m_FPS)); + } + } + } + + float? m_OfflineFps; + public float OfflineFPS + { + get { return m_OfflineFps ?? kDefaultOfflineFps; } + set + { + m_OfflineFps = UnityEngine.Mathf.Clamp(value, kMinFps, kMaxOfflineFps); + if (OfflineFPS != value) + { + OutputWindowScript.Error(string.Format("Offline Video FPS of '{0}' not supported.", value), + string.Format("FPS must be between {0} and {1}.\nFPS set to {2}.", + UnityEngine.Mathf.RoundToInt(kMinFps), + UnityEngine.Mathf.RoundToInt(kMaxOfflineFps), OfflineFPS)); + } + } + } + + float? m_Fov; + public bool FovValid { get { return m_Fov != null; } } + public float Fov + { + get { return m_Fov ?? CameraConfig.kFovDefault; } + set + { + m_Fov = UnityEngine.Mathf.Clamp(value, CameraConfig.kFovMin, CameraConfig.kFovMax); + if (m_Fov != value) + { + OutputWindowScript.Error(string.Format("FOV of '{0}' not supported.", value), + string.Format("FOV must be between {0} and {1}.\nFOV set to {2}.", + CameraConfig.kFovMin, CameraConfig.kFovMax, m_Fov)); + } + } + } + + int? m_Resolution; + public int Resolution + { + get { return m_Resolution ?? kDefaultRes; } + set + { + m_Resolution = UnityEngine.Mathf.Clamp(value, kMinRes, kMaxRes); + if (m_Resolution != value) + { + OutputWindowScript.Error(string.Format("Video Resolution of '{0}' not supported.", value), + string.Format("Resolution must be between {0} and {1}.\nResolution set to {2}.", + kMinRes, kMaxRes, m_Resolution)); + } + } + } + + int? m_OfflineResolution; + public int OfflineResolution + { + get { return m_OfflineResolution ?? kDefaultOfflineRes; } + set + { + m_OfflineResolution = UnityEngine.Mathf.Clamp(value, 640, kMaxOfflineRes); + if (m_OfflineResolution != value) + { + OutputWindowScript.Error(string.Format("Video Resolution of '{0}' not supported.", value), + string.Format("Resolution must be between {0} and {1}.\nResolution set to {2}.", + kMinRes, kMaxOfflineRes, m_OfflineResolution)); + } + } + } + + private bool? m_SaveCameraPath; + public bool SaveCameraPath + { + get { return m_SaveCameraPath ?? true; } + set + { + m_SaveCameraPath = value; + } + } + + string m_VideoEncoder; + public string Encoder + { + get { return m_VideoEncoder ?? kDefaultVideoEncoder; } + set + { + string lowered = value.ToLowerInvariant(); + if (kSupportedVideoEncoders.Contains(lowered)) + { + m_VideoEncoder = lowered; + } + else + { + m_VideoEncoder = null; + OutputWindowScript.Error( + $"VideoEncoder '{lowered}' not supported in {App.kConfigFileName}", + string.Format("Supported: {0}.\nContainer type set to {1}.", + string.Join(", ", kSupportedVideoEncoders.ToArray()), + kDefaultVideoEncoder)); + } + } + } + + string m_ContainerType; + public string ContainerType + { + get { return m_ContainerType ?? kDefaultContainer; } + set + { + string lowered = value.ToLowerInvariant(); + if (kSupportedContainers.Contains(lowered)) + { + m_ContainerType = lowered; + } + else + { + m_ContainerType = null; + OutputWindowScript.Error( + $"ContainerType '{lowered}' not supported in {App.kConfigFileName}", + string.Format("Supported: {0}.\nContainer type set to {1}.", + string.Join(", ", kSupportedContainers.ToArray()), kDefaultContainer)); + } + } + } + + float? m_CameraSmoothing; + public bool CameraSmoothingValid { get { return m_CameraSmoothing != null; } } + public float CameraSmoothing + { + get { return m_CameraSmoothing ?? kDefaultSmoothing; } + set + { + m_CameraSmoothing = UnityEngine.Mathf.Clamp01(value); + if (m_CameraSmoothing != value) + { + OutputWindowScript.Error(string.Format("Camera smoothing of '{0}' not supported.", value), + string.Format("Smoothing must be between 0 and 1.\nSmoothing set to {0}.", + m_CameraSmoothing)); + } + } + } + + float? m_OdsPoleCollapsing; + public float OdsPoleCollapsing + { + get { return m_OdsPoleCollapsing ?? kDefaultOdsPoleCollapsing; } + set + { + m_OdsPoleCollapsing = UnityEngine.Mathf.Clamp01(value); + if (m_OdsPoleCollapsing != value) + { + OutputWindowScript.Error(string.Format("Pole Collapsing of '{0}' not supported.", value), + string.Format("Smoothing must be between 0 and 1.\nPole Collapsing set to {0}.", + m_OdsPoleCollapsing)); + } + } + } + } + + public VideoConfig Video; + + // Settings for the QA testing panel. + [Serializable] + public struct TestingConfig + { + public Dictionary BrushReplacementMap + { + get + { + Dictionary results = new Dictionary(); + if (Config.IsExperimental) + { + if (string.IsNullOrEmpty(BrushReplacements)) + { + return results; + } + var replacements = BrushReplacements.Split(','); + foreach (string replacement in replacements) + { + string[] pair = replacement.Split('='); + if (pair.Length == 2) + { + if (pair[0] == "*") + { + Guid guid = new Guid(pair[1]); + foreach (var brush in App.Instance.m_Manifest.Brushes) + { + results.Add(brush.m_Guid, guid); + } + } + else + { + results.Add(new Guid(pair[0]), new Guid(pair[1])); + } + } + else + { + OutputWindowScript.Error("BrushReplacement should be of the form:\n" + + "brushguidA=brushguidB,brushguidC=brushguidD"); + } + } + } + return results; + } + } + + public bool Enabled; + public string InputFile; + public string OutputFile; + public bool ResetPromos; + public bool FirstRun; + public string BrushReplacements; + } + public TestingConfig Testing; + + // Profiling Settings + [Serializable] + public struct ProfilingConfig + { + public const int kDefaultScreenshotResolution = 1000; + public string[] ProfilingFunctions { get; private set; } + public ProfilingManager.Mode ProfilingMode { get; private set; } + + public string Mode + { + set + { + try + { + ProfilingMode = (ProfilingManager.Mode)Enum.Parse(typeof(ProfilingManager.Mode), value); + } + catch (ArgumentException) + { + OutputWindowScript.Error(string.Format("'{0}' is not a valid profiling mode.", value)); + } + } + } + + public string Functions + { + set { ProfilingFunctions = value.Split(','); } + } + + public string ProfileName; + public string ProfileFilename; + public string SketchToLoad; + public bool AutoProfile; + public bool ShowControllers; + + public float Duration + { + get { return m_Duration.HasValue ? m_Duration.Value : 5f; } + set { m_Duration = value; } + } + private float? m_Duration; + + public bool Csv; + + // Any invalid quality level is ignored. + private int? m_QualityLevel; + public int QualityLevel + { + get { return m_QualityLevel.HasValue ? m_QualityLevel.Value : -1; } + set { m_QualityLevel = value; } + } + + public float ViewportScaling { get; set; } + public float EyeTextureScaling { get; set; } + public int GlobalMaximumLOD { get; set; } + public int MsaaLevel { get; set; } + public bool TakeScreenshot { get; set; } + private int? m_screenshotResolution; + + public int ScreenshotResolution + { + get + { + return m_screenshotResolution.HasValue ? + m_screenshotResolution.Value : kDefaultScreenshotResolution; + } + set { m_screenshotResolution = value; } + } + public bool PerfgateOutput { get; set; } + + private float? m_StrokeSimplification; + + public float StrokeSimplification + { + get { return m_StrokeSimplification.HasValue ? m_StrokeSimplification.Value : 0f; } + set { m_StrokeSimplification = value; } + } + + public bool HasStrokeSimplification + { + get { return m_StrokeSimplification.HasValue; } + } + } + public ProfilingConfig Profiling; + } + +} // namespace TiltBrush diff --git a/Assets/Scripts/Util/AxisConvention.cs b/Assets/Scripts/Util/AxisConvention.cs index 391997ec10..465e3329e4 100644 --- a/Assets/Scripts/Util/AxisConvention.cs +++ b/Assets/Scripts/Util/AxisConvention.cs @@ -38,7 +38,7 @@ public struct AxisConvention }; // When we implemented Poly support the gltf spec didn't specify a forward direction. - public static readonly AxisConvention kGltfAccordingToPoly = new AxisConvention + public static readonly AxisConvention kGltfAccordingToIcosa = new AxisConvention { right = new Vector3(1, 0, 0), up = new Vector3(0, 1, 0), diff --git a/Assets/Scripts/Util/ImageUtils.cs b/Assets/Scripts/Util/ImageUtils.cs index 6fa81a9bf7..1ca8bd47f1 100644 --- a/Assets/Scripts/Util/ImageUtils.cs +++ b/Assets/Scripts/Util/ImageUtils.cs @@ -1,486 +1,486 @@ -// Copyright 2020 The Tilt Brush Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// 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.Threading.Tasks; -using UnityEngine; -using UnityEngine.Networking; - -namespace TiltBrush -{ - - - - public class ImageLoadError : Exception - { - - public enum ImageLoadErrorCode - { - // This is the default one; errors like unknown format, corruption, etc. - ImageGenericError, - // too large dimensions - ImageTooLargeError - } - - public ImageLoadErrorCode imageLoadErrorCode = ImageLoadErrorCode.ImageGenericError; - - public ImageLoadError(string message) : base(message) { } - public ImageLoadError(string fmt, params System.Object[] args) - : base(string.Format(fmt, args)) - { - } - public ImageLoadError(Exception inner, string fmt, params System.Object[] args) - : base(string.Format(fmt, args), inner) - { - } - - public ImageLoadError(string message, ImageLoadErrorCode imageLoadErrorCode) : base(message) - { - this.imageLoadErrorCode = imageLoadErrorCode; - } - } - - static public class ImageUtils - { - const byte kJpegMarkerSOF0 = (byte)0xc0; - const byte kJpegMarkerSOF2 = (byte)0xc2; - - /// Raises TiltBrush.ImageDecodeError if the data is not in a supported image format. - /// Raises TiltBrush.ImageTooLargeError if abortSize > 0 and the image width or height - /// are larger than abortSize. - static public RawImage FromImageData( - byte[] data, string filename, int abortDimension = -1) - { - if (abortDimension > 0) - { - ValidateDimensions(data, abortDimension); - } - - if (IsJpeg(data)) - { - return FromJpeg(data, filename); - } - else if (IsPng(data)) - { - return FromPng(data, filename); - } - else - { - throw new ImageLoadError("Unknown/unsupported format"); - } - } - - static public void ValidateDimensions(byte[] data, int maxDimension) - { - int imageWidth = 0; - int imageHeight = 0; - using (var stream = new MemoryStream(data)) - { - if (IsJpeg(data)) - { - bool ok = GetJpegWidthAndHeight(stream, out imageWidth, out imageHeight); - if (!ok) - { - throw new ImageLoadError("Failed to get dimensions from jpeg"); - } - } - else if (IsPng(data)) - { - GetPngWidthAndHeight(stream, out imageWidth, out imageHeight); - } - else - { - throw new ImageLoadError("Can't get dimensions from unknown image format!"); - } - } - - // Cast to long as maxDimension is big enough on desktop to overflow - if (imageWidth * imageHeight > ((long)maxDimension * (long)maxDimension)) - { - throw new ImageLoadError( - String.Format("Image dimensions {0}x{1} are greater than max dimensions of {2}x{2}!", - imageWidth, imageHeight, maxDimension), ImageLoadError.ImageLoadErrorCode.ImageTooLargeError); - } - } - - /// Returns true if the data looks like it might be a jpeg - static public bool IsJpeg(byte[] data) - { - return ( - data.Length >= 3 && - data[0] == 0xff && data[1] == 0xd8 && /* SOI tag */ - data[2] == 0xff /* Start of some other tag */); - } - - // [MustUseReturnValue] -- Unity doesn't seem to contain this annotation?! - // Should probably return (int, int)? instead - static public bool GetJpegWidthAndHeight(Stream stream, - out int width, out int height) - { - width = 0; - height = 0; - - byte marker = 0; - byte[] twoBytes = new byte[2]; - JPEGBinaryReader reader = new JPEGBinaryReader(stream); - - // Run through all the markers in the jpeg and look for the SOF, or start of frames. - // Most .jpegs have one SOF, but some have many. - // We're concerned with the size of this image, so take the largest of any frames we find. - while (true) - { - switch (marker) - { - case kJpegMarkerSOF0: - case kJpegMarkerSOF2: - // Skip the frame length. - reader.ReadInt16(); - // Bits percision. - reader.ReadByte(); - // Scan lines (height) - twoBytes = reader.ReadBytes(2); - height = Mathf.Max(height, (twoBytes[0] << 8) + twoBytes[1]); - // Scan samples per line (width) - twoBytes = reader.ReadBytes(2); - width = Mathf.Max(width, (twoBytes[0] << 8) + twoBytes[1]); - return true; - } - - try - { - marker = reader.GetNextMarker(); - } - catch (System.IO.EndOfStreamException) - { - break; /* done reading the file */ - } - } - return false; - } - - /// Raises TiltBrush.ImageDecodeError if the data is not a valid jpeg - static public RawImage FromJpeg(byte[] jpegData, string filename) - { - using (var stream = new MemoryStream(jpegData)) - { - FluxJpeg.Core.Image image; - try - { - FluxJpeg.Core.DecodedJpeg decoded = - new FluxJpeg.Core.Decoder.JpegDecoder(stream).Decode(); - image = decoded.Image; - image.ChangeColorSpace(FluxJpeg.Core.ColorSpace.RGB); - } - catch (Exception e) - { - // Library throws bare Exception :-P - throw new ImageLoadError(e, "JPEG decode error"); - } - - var reds = image.Raster[0]; - var greens = image.Raster[1]; - var blues = image.Raster[2]; - int _width = image.Width; - int _height = image.Height; - var buf = new Color32[_width * _height]; - unsafe - { - unchecked - { - fixed (Color32* pBuf = buf) - { - byte* cur = (byte*)pBuf; - for (int y = _height - 1; y >= 0; --y) - { - for (int x = 0; x < _width; ++x) - { - cur[0] = reds[x, y]; - cur[1] = greens[x, y]; - cur[2] = blues[x, y]; - cur[3] = 0xff; - cur += 4; - } - } - } - } - } - return new RawImage - { - ColorData = buf, - ColorWidth = _width, - ColorHeight = _height, - ColorAspect = _height == 0 ? 1f : ((float)_width / _height) - }; - } - } - - /// Returns true if the data look slike it might be a png - static public bool IsPng(byte[] data) - { - return ( - data.Length >= 8 && - data[0] == 0x89 && - data[1] == 'P' && data[2] == 'N' && data[3] == 'G' && // "PNG" - data[4] == '\r' && data[5] == '\n' && // CRLF - data[6] == 0x1a && // DOS EOF - data[7] == '\n'); - } - - static public void GetPngWidthAndHeight(System.IO.Stream stream, - out int width, out int height) - { - BinaryReader br = new BinaryReader(stream); - // Skip signature. - br.ReadBytes(16); - - byte[] fourBytes = new byte[4]; - fourBytes = br.ReadBytes(4); - width = (fourBytes[0] << 24) + (fourBytes[1] << 16) + - (fourBytes[2] << 8) + fourBytes[3]; - - fourBytes = br.ReadBytes(4); - height = (fourBytes[0] << 24) + (fourBytes[1] << 16) + - (fourBytes[2] << 8) + fourBytes[3]; - } - - /// Raises TiltBrush.ImageDecodeError if the data is not a valid png. - static public RawImage FromPng(byte[] pngData, string filename) - { - try - { - return _FromPng(pngData, filename); - } - catch (Exception e) - { - // There are a ton of different exceptions it can throw, and there - // is no convenient base class - throw new ImageLoadError(e, "PNG decode error"); - } - } - - static RawImage _FromPng(byte[] pngData, string filename) - { - // TODO: test the untested branches - using (var stream = new MemoryStream(pngData)) - { - var png = new Hjg.Pngcs.PngReader(stream, filename); - png.SetUnpackedMode(true); - - int rows = png.ImgInfo.Rows; - int cols = png.ImgInfo.Cols; - int chans = png.ImgInfo.Channels; - - Color32[] buf = new Color32[rows * cols]; - - if (png.ImgInfo.Indexed) - { - var plte = png.GetMetadata().GetPLTE(); - - byte[] alphas = new byte[256]; - { - for (int i = 0; i < 256; ++i) - { - alphas[i] = 255; - } - var trns = png.GetMetadata().GetTRNS(); - if (trns != null) - { - // might be smaller than 256 - int[] palette = trns.GetPalletteAlpha(); - for (int i = 0; i < palette.Length; ++i) - { - alphas[i] = (byte)palette[i]; - } - } - } - - byte[] line = null; - int[] rgb = new int[3]; - for (int r = 0; r < rows; ++r) - { - line = png.ReadRowByte(line, r); - for (int c = 0; c < cols; ++c) - { - int iEntry = line[c]; - plte.GetEntryRgb(iEntry, rgb); - byte alpha = alphas[iEntry]; - buf[(rows - r - 1) * cols + c] = new Color32((byte)rgb[0], (byte)rgb[1], (byte)rgb[2], alpha); - } - } - } - else if (png.ImgInfo.Greyscale && !png.ImgInfo.Alpha) - { - Debug.Assert(chans == 1); - Debug.Assert(png.ImgInfo.BitDepth <= 8, "Unsupported: 16-bit grey"); - - byte[] line = null; - for (int r = 0; r < rows; ++r) - { - line = png.ReadRowByte(line, r); - for (int c = 0; c < cols; ++c) - { - buf[(rows - r - 1) * cols + c] = new Color32(line[c], line[c], line[c], 255); - } - } - } - else if (png.ImgInfo.Greyscale && png.ImgInfo.Alpha) - { - Debug.Assert(chans == 2); - Debug.Assert(png.ImgInfo.BitDepth <= 8, "Unsupported: 16-bit grey"); - Debug.Assert(false, "currently unsupported: grayscale alpha"); - - byte[] line = null; - for (int r = 0; r < rows; ++r) - { - line = png.ReadRowByte(line, r); - for (int c = 0; c < cols; ++c) - { - int i = c * chans; - buf[(rows - r - 1) * cols + c] = new Color32(line[i], line[i], line[i], line[i + 1]); - } - } - } - else if (chans == 3 || chans == 4) - { - // Can use ReadRowByte() if bitDepth <= 8 - if (png.ImgInfo.BitDepth <= 8) - { - byte[] line = null; - for (int r = 0; r < rows; ++r) - { - line = png.ReadRowByte(line, r); - for (int c = 0; c < cols; ++c) - { - int ichan = c * chans; - buf[(rows - r - 1) * cols + c] = new Color32( - line[ichan], line[ichan + 1], line[ichan + 2], - (chans == 3) ? (byte)0xff : line[ichan + 3]); - } - } - } - else - { - Debug.Assert(png.ImgInfo.BitDepth == 16); - Debug.Assert(false, "Untested: 16-bit rgb"); - var lines = png.ReadRowsInt(0, png.ImgInfo.Rows, 1); - for (int r = 0; r < rows; ++r) - { - int[] line = lines.Scanlines[r]; - for (int c = 0; c < cols; ++c) - { - int ichan = c * chans; - buf[(rows - r - 1) * cols + c] = new Color32( - (byte)line[ichan], (byte)line[ichan + 1], (byte)line[ichan + 2], - (byte)((chans == 3) ? 0xff : line[ichan + 3])); - } - } - } - } - else - { - Debug.Assert(false, "Weird format"); - } - - return new RawImage - { - ColorData = buf, - ColorWidth = cols, - ColorHeight = rows, - ColorAspect = (rows == 0) ? 1f : ((float)cols / rows) - }; - } - } - - /// Fetches the url and returns a Texture2D or null. - public static async Task DownloadTextureAsync(string uri) - { - using (UnityWebRequest www = UnityWebRequestTexture.GetTexture(uri)) - { - await www.SendWebRequest(); - // If we don't do this, downloadHandler.data sometimes (always?) returns garbage - while (!www.downloadHandler.isDone) - { - await Awaiters.NextFrame; - } - - if (www.isNetworkError || www.responseCode >= 400) - { - Debug.LogErrorFormat("ImageUtils: Error downloading {0}, error {1}", uri, www.responseCode); - return null; - } - - - // Try LoadImage first, because it's faster - { - Texture2D dest = new Texture2D(2, 2); - if (dest.LoadImage(www.downloadHandler.data)) - { - if (dest.width == 8) - { - // Detect "false success" from LoadImage -- if we see this at all, we should - // consider falling through to ThreadedImageReader? - Debug.LogError("Got 8x8 from LoadImage!"); - } - return dest; - } - else - { - Debug.LogError("DownloadTextureAsync: LoadImage failed"); // Unexpected - } - UnityEngine.Object.Destroy(dest); - } - - // This case probably won't get hit any more - { - RawImage im; - try - { - im = await new ThreadedImageReader(www.downloadHandler.data, uri); - } - catch (ImageLoadError e) - { - Console.WriteLine($"ImageUtils: cannot hand-create {uri}: {e}"); - im = null; - } - if (im != null) - { - Console.WriteLine($"ImageUtils: hand-creating {uri}: {www.isDone}"); - Texture2D dest = new Texture2D(im.ColorWidth, im.ColorHeight, TextureFormat.RGBA32, true); - dest.SetPixels32(im.ColorData); - dest.Apply(); - Console.WriteLine("ImageUtils: hand-created icon dimensions: " + - $"{dest.width}, {dest.height}"); - return dest; - } - } - - // b/37256058: Unity's DownloadHandlerTexture is buggy in 5.4.4 and returns Textures - // which hard-crash Unity (for some URLs, sometimes). - // That bug may be fixed by now, but since it doesn't show up in analytics and is - // quite severeTry creating the texture ourselves. - // Fall through to doing it the old, maybe b/37256058 buggy way. - // This case should get hit even less than the previous case. - { - Console.WriteLine("ImageUtils: downloaded and handled {0}: {1} {2}", - uri, www.isDone, www.downloadHandler.isDone); - // b/62269743: sometimes this returns an ugly 8x8 texture. - Texture2D dest = DownloadHandlerTexture.GetContent(www); - Console.WriteLine($"ImageUtils: icon dimensions: {dest.width}, {dest.height}"); - return dest; - } - } - } - } // ImageUtils -} // TiltBrush +// Copyright 2020 The Tilt Brush Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// 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.Threading.Tasks; +using UnityEngine; +using UnityEngine.Networking; + +namespace TiltBrush +{ + + + + public class ImageLoadError : Exception + { + + public enum ImageLoadErrorCode + { + // This is the default one; errors like unknown format, corruption, etc. + ImageGenericError, + // too large dimensions + ImageTooLargeError + } + + public ImageLoadErrorCode imageLoadErrorCode = ImageLoadErrorCode.ImageGenericError; + + public ImageLoadError(string message) : base(message) { } + public ImageLoadError(string fmt, params System.Object[] args) + : base(string.Format(fmt, args)) + { + } + public ImageLoadError(Exception inner, string fmt, params System.Object[] args) + : base(string.Format(fmt, args), inner) + { + } + + public ImageLoadError(string message, ImageLoadErrorCode imageLoadErrorCode) : base(message) + { + this.imageLoadErrorCode = imageLoadErrorCode; + } + } + + static public class ImageUtils + { + const byte kJpegMarkerSOF0 = (byte)0xc0; + const byte kJpegMarkerSOF2 = (byte)0xc2; + + /// Raises TiltBrush.ImageDecodeError if the data is not in a supported image format. + /// Raises TiltBrush.ImageTooLargeError if abortSize > 0 and the image width or height + /// are larger than abortSize. + static public RawImage FromImageData( + byte[] data, string filename, int abortDimension = -1) + { + if (abortDimension > 0) + { + ValidateDimensions(data, abortDimension); + } + + if (IsJpeg(data)) + { + return FromJpeg(data, filename); + } + else if (IsPng(data)) + { + return FromPng(data, filename); + } + else + { + throw new ImageLoadError("Unknown/unsupported format"); + } + } + + static public void ValidateDimensions(byte[] data, int maxDimension) + { + int imageWidth = 0; + int imageHeight = 0; + using (var stream = new MemoryStream(data)) + { + if (IsJpeg(data)) + { + bool ok = GetJpegWidthAndHeight(stream, out imageWidth, out imageHeight); + if (!ok) + { + throw new ImageLoadError("Failed to get dimensions from jpeg"); + } + } + else if (IsPng(data)) + { + GetPngWidthAndHeight(stream, out imageWidth, out imageHeight); + } + else + { + throw new ImageLoadError("Can't get dimensions from unknown image format!"); + } + } + + // Cast to long as maxDimension is big enough on desktop to overflow + if (imageWidth * imageHeight > ((long)maxDimension * (long)maxDimension)) + { + throw new ImageLoadError( + String.Format("Image dimensions {0}x{1} are greater than max dimensions of {2}x{2}!", + imageWidth, imageHeight, maxDimension), ImageLoadError.ImageLoadErrorCode.ImageTooLargeError); + } + } + + /// Returns true if the data looks like it might be a jpeg + static public bool IsJpeg(byte[] data) + { + return ( + data.Length >= 3 && + data[0] == 0xff && data[1] == 0xd8 && /* SOI tag */ + data[2] == 0xff /* Start of some other tag */); + } + + // [MustUseReturnValue] -- Unity doesn't seem to contain this annotation?! + // Should probably return (int, int)? instead + static public bool GetJpegWidthAndHeight(Stream stream, + out int width, out int height) + { + width = 0; + height = 0; + + byte marker = 0; + byte[] twoBytes = new byte[2]; + JPEGBinaryReader reader = new JPEGBinaryReader(stream); + + // Run through all the markers in the jpeg and look for the SOF, or start of frames. + // Most .jpegs have one SOF, but some have many. + // We're concerned with the size of this image, so take the largest of any frames we find. + while (true) + { + switch (marker) + { + case kJpegMarkerSOF0: + case kJpegMarkerSOF2: + // Skip the frame length. + reader.ReadInt16(); + // Bits percision. + reader.ReadByte(); + // Scan lines (height) + twoBytes = reader.ReadBytes(2); + height = Mathf.Max(height, (twoBytes[0] << 8) + twoBytes[1]); + // Scan samples per line (width) + twoBytes = reader.ReadBytes(2); + width = Mathf.Max(width, (twoBytes[0] << 8) + twoBytes[1]); + return true; + } + + try + { + marker = reader.GetNextMarker(); + } + catch (System.IO.EndOfStreamException) + { + break; /* done reading the file */ + } + } + return false; + } + + /// Raises TiltBrush.ImageDecodeError if the data is not a valid jpeg + static public RawImage FromJpeg(byte[] jpegData, string filename) + { + using (var stream = new MemoryStream(jpegData)) + { + FluxJpeg.Core.Image image; + try + { + FluxJpeg.Core.DecodedJpeg decoded = + new FluxJpeg.Core.Decoder.JpegDecoder(stream).Decode(); + image = decoded.Image; + image.ChangeColorSpace(FluxJpeg.Core.ColorSpace.RGB); + } + catch (Exception e) + { + // Library throws bare Exception :-P + throw new ImageLoadError(e, "JPEG decode error"); + } + + var reds = image.Raster[0]; + var greens = image.Raster[1]; + var blues = image.Raster[2]; + int _width = image.Width; + int _height = image.Height; + var buf = new Color32[_width * _height]; + unsafe + { + unchecked + { + fixed (Color32* pBuf = buf) + { + byte* cur = (byte*)pBuf; + for (int y = _height - 1; y >= 0; --y) + { + for (int x = 0; x < _width; ++x) + { + cur[0] = reds[x, y]; + cur[1] = greens[x, y]; + cur[2] = blues[x, y]; + cur[3] = 0xff; + cur += 4; + } + } + } + } + } + return new RawImage + { + ColorData = buf, + ColorWidth = _width, + ColorHeight = _height, + ColorAspect = _height == 0 ? 1f : ((float)_width / _height) + }; + } + } + + /// Returns true if the data look slike it might be a png + static public bool IsPng(byte[] data) + { + return ( + data.Length >= 8 && + data[0] == 0x89 && + data[1] == 'P' && data[2] == 'N' && data[3] == 'G' && // "PNG" + data[4] == '\r' && data[5] == '\n' && // CRLF + data[6] == 0x1a && // DOS EOF + data[7] == '\n'); + } + + static public void GetPngWidthAndHeight(System.IO.Stream stream, + out int width, out int height) + { + BinaryReader br = new BinaryReader(stream); + // Skip signature. + br.ReadBytes(16); + + byte[] fourBytes = new byte[4]; + fourBytes = br.ReadBytes(4); + width = (fourBytes[0] << 24) + (fourBytes[1] << 16) + + (fourBytes[2] << 8) + fourBytes[3]; + + fourBytes = br.ReadBytes(4); + height = (fourBytes[0] << 24) + (fourBytes[1] << 16) + + (fourBytes[2] << 8) + fourBytes[3]; + } + + /// Raises TiltBrush.ImageDecodeError if the data is not a valid png. + static public RawImage FromPng(byte[] pngData, string filename) + { + try + { + return _FromPng(pngData, filename); + } + catch (Exception e) + { + // There are a ton of different exceptions it can throw, and there + // is no convenient base class + throw new ImageLoadError(e, "PNG decode error"); + } + } + + static RawImage _FromPng(byte[] pngData, string filename) + { + // TODO: test the untested branches + using (var stream = new MemoryStream(pngData)) + { + var png = new Hjg.Pngcs.PngReader(stream, filename); + png.SetUnpackedMode(true); + + int rows = png.ImgInfo.Rows; + int cols = png.ImgInfo.Cols; + int chans = png.ImgInfo.Channels; + + Color32[] buf = new Color32[rows * cols]; + + if (png.ImgInfo.Indexed) + { + var plte = png.GetMetadata().GetPLTE(); + + byte[] alphas = new byte[256]; + { + for (int i = 0; i < 256; ++i) + { + alphas[i] = 255; + } + var trns = png.GetMetadata().GetTRNS(); + if (trns != null) + { + // might be smaller than 256 + int[] palette = trns.GetPalletteAlpha(); + for (int i = 0; i < palette.Length; ++i) + { + alphas[i] = (byte)palette[i]; + } + } + } + + byte[] line = null; + int[] rgb = new int[3]; + for (int r = 0; r < rows; ++r) + { + line = png.ReadRowByte(line, r); + for (int c = 0; c < cols; ++c) + { + int iEntry = line[c]; + plte.GetEntryRgb(iEntry, rgb); + byte alpha = alphas[iEntry]; + buf[(rows - r - 1) * cols + c] = new Color32((byte)rgb[0], (byte)rgb[1], (byte)rgb[2], alpha); + } + } + } + else if (png.ImgInfo.Greyscale && !png.ImgInfo.Alpha) + { + Debug.Assert(chans == 1); + Debug.Assert(png.ImgInfo.BitDepth <= 8, "Unsupported: 16-bit grey"); + + byte[] line = null; + for (int r = 0; r < rows; ++r) + { + line = png.ReadRowByte(line, r); + for (int c = 0; c < cols; ++c) + { + buf[(rows - r - 1) * cols + c] = new Color32(line[c], line[c], line[c], 255); + } + } + } + else if (png.ImgInfo.Greyscale && png.ImgInfo.Alpha) + { + Debug.Assert(chans == 2); + Debug.Assert(png.ImgInfo.BitDepth <= 8, "Unsupported: 16-bit grey"); + Debug.Assert(false, "currently unsupported: grayscale alpha"); + + byte[] line = null; + for (int r = 0; r < rows; ++r) + { + line = png.ReadRowByte(line, r); + for (int c = 0; c < cols; ++c) + { + int i = c * chans; + buf[(rows - r - 1) * cols + c] = new Color32(line[i], line[i], line[i], line[i + 1]); + } + } + } + else if (chans == 3 || chans == 4) + { + // Can use ReadRowByte() if bitDepth <= 8 + if (png.ImgInfo.BitDepth <= 8) + { + byte[] line = null; + for (int r = 0; r < rows; ++r) + { + line = png.ReadRowByte(line, r); + for (int c = 0; c < cols; ++c) + { + int ichan = c * chans; + buf[(rows - r - 1) * cols + c] = new Color32( + line[ichan], line[ichan + 1], line[ichan + 2], + (chans == 3) ? (byte)0xff : line[ichan + 3]); + } + } + } + else + { + Debug.Assert(png.ImgInfo.BitDepth == 16); + Debug.Assert(false, "Untested: 16-bit rgb"); + var lines = png.ReadRowsInt(0, png.ImgInfo.Rows, 1); + for (int r = 0; r < rows; ++r) + { + int[] line = lines.Scanlines[r]; + for (int c = 0; c < cols; ++c) + { + int ichan = c * chans; + buf[(rows - r - 1) * cols + c] = new Color32( + (byte)line[ichan], (byte)line[ichan + 1], (byte)line[ichan + 2], + (byte)((chans == 3) ? 0xff : line[ichan + 3])); + } + } + } + } + else + { + Debug.Assert(false, "Weird format"); + } + + return new RawImage + { + ColorData = buf, + ColorWidth = cols, + ColorHeight = rows, + ColorAspect = (rows == 0) ? 1f : ((float)cols / rows) + }; + } + } + + /// Fetches the url and returns a Texture2D or null. + public static async Task DownloadTextureAsync(string uri) + { + using (UnityWebRequest www = UnityWebRequestTexture.GetTexture(uri)) + { + await www.SendWebRequest(); + // If we don't do this, downloadHandler.data sometimes (always?) returns garbage + while (!www.downloadHandler.isDone) + { + await Awaiters.NextFrame; + } + + if (www.isNetworkError || www.responseCode >= 400) + { + Debug.LogErrorFormat("ImageUtils: Error downloading {0}, error {1}", uri, www.responseCode); + return null; + } + + + // Try LoadImage first, because it's faster + { + Texture2D dest = new Texture2D(2, 2); + if (dest.LoadImage(www.downloadHandler.data)) + { + if (dest.width == 8) + { + // Detect "false success" from LoadImage -- if we see this at all, we should + // consider falling through to ThreadedImageReader? + Debug.LogError("Got 8x8 from LoadImage!"); + } + return dest; + } + else + { + Debug.LogError("DownloadTextureAsync: LoadImage failed"); // Unexpected + } + UnityEngine.Object.Destroy(dest); + } + + // This case probably won't get hit any more + { + RawImage im; + try + { + im = await new ThreadedImageReader(www.downloadHandler.data, uri); + } + catch (ImageLoadError e) + { + Console.WriteLine($"ImageUtils: cannot hand-create {uri}: {e}"); + im = null; + } + if (im != null) + { + Console.WriteLine($"ImageUtils: hand-creating {uri}: {www.isDone}"); + Texture2D dest = new Texture2D(im.ColorWidth, im.ColorHeight, TextureFormat.RGBA32, true); + dest.SetPixels32(im.ColorData); + dest.Apply(); + Console.WriteLine("ImageUtils: hand-created icon dimensions: " + + $"{dest.width}, {dest.height}"); + return dest; + } + } + + // b/37256058: Unity's DownloadHandlerTexture is buggy in 5.4.4 and returns Textures + // which hard-crash Unity (for some URLs, sometimes). + // That bug may be fixed by now, but since it doesn't show up in analytics and is + // quite severeTry creating the texture ourselves. + // Fall through to doing it the old, maybe b/37256058 buggy way. + // This case should get hit even less than the previous case. + { + Console.WriteLine("ImageUtils: downloaded and handled {0}: {1} {2}", + uri, www.isDone, www.downloadHandler.isDone); + // b/62269743: sometimes this returns an ugly 8x8 texture. + Texture2D dest = DownloadHandlerTexture.GetContent(www); + Console.WriteLine($"ImageUtils: icon dimensions: {dest.width}, {dest.height}"); + return dest; + } + } + } + } // ImageUtils +} // TiltBrush diff --git a/Assets/Scripts/WidgetManager.cs b/Assets/Scripts/WidgetManager.cs index e9b5e445fe..7169e8124e 100644 --- a/Assets/Scripts/WidgetManager.cs +++ b/Assets/Scripts/WidgetManager.cs @@ -1,1559 +1,1559 @@ -//// Copyright 2020 The Tilt Brush Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// 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.Linq; -using System.Collections.Generic; -using UnityEngine; - -namespace TiltBrush -{ - - // These names are used in our save format, so they must be protected from obfuscation - // Do not change the names of any of them, unless they've never been released. - [Serializable] - public enum StencilType - { - Plane, - Cube, - Sphere, - Capsule, - Cone, - Cylinder, - InteriorDome, - Pyramid, - Ellipsoid - } - - [Serializable] - public struct StencilMapKey - { - public StencilType m_Type; - public StencilWidget m_StencilPrefab; - } - - public struct StencilContactInfo - { - public StencilWidget widget; - public Vector3 pos; - public Vector3 normal; - } - - public class GrabWidgetData - { - public readonly GameObject m_WidgetObject; - public readonly GrabWidget m_WidgetScript; - - // These fields are only valid during a call to GetNearestGrabWidget, - // and are undefined afterwards. Do not use them. - - public bool m_NearController; - // only valid if m_NearController == true - public float m_ControllerScore; - - public GrabWidgetData(GrabWidget widget) - { - m_WidgetScript = widget; - m_WidgetObject = widget.gameObject; - } - // Could maybe get by without this since all users of Clone() don't care if they - // receive a plain old GrabWidgetData or not. - public virtual GrabWidgetData Clone() - { - return new GrabWidgetData(m_WidgetScript) - { - m_NearController = m_NearController, - m_ControllerScore = m_ControllerScore - }; - } - } - - public class TypedWidgetData : GrabWidgetData where T : GrabWidget - { - private readonly T m_typedWidget; - public new T WidgetScript => m_typedWidget; - public TypedWidgetData(T widget) : base(widget) - { - m_typedWidget = widget; - } - public override GrabWidgetData Clone() - { - return new TypedWidgetData(m_typedWidget) - { - m_NearController = m_NearController, - m_ControllerScore = m_ControllerScore - }; - } - } - - public class WidgetManager : MonoBehaviour - { - static public WidgetManager m_Instance; - - [SerializeField] ModelWidget m_ModelWidgetPrefab; - [SerializeField] GameObject m_WidgetPinPrefab; - [SerializeField] ImageWidget m_ImageWidgetPrefab; - [SerializeField] VideoWidget m_VideoWidgetPrefab; - [SerializeField] LightWidget m_LightWidgetPrefab; - [SerializeField] SceneLightGizmo m_SceneLightGizmoPrefab; - [SerializeField] CameraPathWidget m_CameraPathWidgetPrefab; - [SerializeField] private GameObject m_CameraPathPositionKnotPrefab; - [SerializeField] private GameObject m_CameraPathRotationKnotPrefab; - [SerializeField] private GameObject m_CameraPathSpeedKnotPrefab; - [SerializeField] private GameObject m_CameraPathFovKnotPrefab; - [SerializeField] private GameObject m_CameraPathKnotSegmentPrefab; - [SerializeField] private GrabWidgetHome m_Home; - [SerializeField] private GameObject m_HomeHintLinePrefab; - [SerializeField] float m_WidgetSnapAngle = 15.0f; - [SerializeField] float m_GazeMaxAngleFromFacing = 70.0f; - [SerializeField] private float m_PanelFocusActivationScore; - [SerializeField] private float m_ModelVertCountScalar = 1.0f; - - [Header("Stencils")] - [SerializeField] StencilMapKey[] m_StencilMap; - [SerializeField] private float m_StencilAttractDist = 0.5f; - [SerializeField] private float m_StencilAttachHysteresis = 0.1f; - [SerializeField] private string m_StencilLayerName; - [SerializeField] private string m_PinnedStencilLayerName; - - private bool m_WidgetsDormant; - private bool m_InhibitGrabWhileLoading; - - private GameObject m_HomeHintLine; - private MeshFilter m_HomeHintLineMeshFilter; - private Vector3 m_HomeHintLineBaseScale; - - private StencilContactInfo[] m_StencilContactInfos; - private const int m_StencilBucketSize = 16; - private StencilWidget m_ActiveStencil; - private bool m_StencilsDisabled; - - // All grabbable widgets should be in exactly one of these lists. - // Widgets will be in the most specific list. - private List m_GrabWidgets; - private List> m_ModelWidgets; - private List> m_LightWidgets; - private List> m_StencilWidgets; - private List> m_ImageWidgets; - private List> m_VideoWidgets; - private List> m_CameraPathWidgets; - - // These lists are used by the PinTool. They're kept in sync by the - // widget manager, but the PinTool is responsible for their coherency. - private List m_CanBePinnedWidgets; - private List m_CanBeUnpinnedWidgets; - public event Action RefreshPinAndUnpinAction; - - private TiltModels75[] m_loadingTiltModels75; - private TiltLights[] m_loadingTiltLights; - private TiltImages75[] m_loadingTiltImages75; - private TiltVideo[] m_loadingTiltVideos; - - private List m_WidgetsNearBrush; - private List m_WidgetsNearWand; - - // This value is used by SketchMemoryScript to check the sketch against memory limits. - // It's incremented when a model is registered, and decremented when a model is - // unregistered. - private int m_ModelVertCount; - // Similar to above, this value is used to check against memory limits. Images are always - // the same number of verts, however, so this number is scaled by texture size. It's a - // hand-wavey calculation. - private int m_ImageVertCount; - - // Camera path. - [NonSerialized] public bool FollowingPath; - private TypedWidgetData m_CurrentCameraPath; - private bool m_CameraPathsVisible; - private CameraPathTinter m_CameraPathTinter; - - static private Dictionary sm_BatchMap = new Dictionary(); - public bool m_EnableSnapToGuides; - - public StencilWidget ActiveStencil - { - get { return m_ActiveStencil; } - } - - public void ResetActiveStencil() - { - m_ActiveStencil = null; - } - - public int StencilLayerIndex - { - get { return LayerMask.NameToLayer(m_StencilLayerName); } - } - - public int PinnedStencilLayerIndex - { - get { return LayerMask.NameToLayer(m_PinnedStencilLayerName); } - } - - public LayerMask PinnedStencilLayerMask - { - get { return LayerMask.GetMask(m_PinnedStencilLayerName); } - } - - public LayerMask StencilLayerMask - { - get { return LayerMask.GetMask(m_StencilLayerName); } - } - - public float StencilAttractDist - { - get => m_StencilAttractDist; - set - { - m_StencilAttractDist = value; - App.Switchboard.TriggerStencilAttractDistChanged(); - } - } - - public List WidgetsNearBrush - { - get { return m_WidgetsNearBrush; } - } - - public List WidgetsNearWand - { - get { return m_WidgetsNearWand; } - } - - public bool AnyWidgetsToPin - { - get { return m_CanBePinnedWidgets.Count > 0; } - } - - public bool AnyWidgetsToUnpin - { - get { return m_CanBeUnpinnedWidgets.Count > 0; } - } - - public float ModelVertCountScalar - { - get { return m_ModelVertCountScalar; } - } - - public int ImageVertCount - { - get { return m_ImageVertCount; } - } - - public void AdjustModelVertCount(int amount) - { - m_ModelVertCount += amount; - } - - public void AdjustImageVertCount(int amount) - { - m_ImageVertCount += amount; - } - - public int WidgetsVertCount - { - get { return m_ModelVertCount + m_ImageVertCount; } - } - - public bool AnyVideoWidgetActive => m_VideoWidgets.Any(x => x.m_WidgetObject.activeSelf); - - public bool AnyCameraPathWidgetsActive => - m_CameraPathWidgets.Any(x => x.m_WidgetObject.activeSelf); - - public CameraPathTinter PathTinter { get => m_CameraPathTinter; } - - // Returns the associated widget for the given batchId. - // Returns null if key doesn't exist. - public GrabWidget GetBatch(ushort batchId) - { - if (sm_BatchMap.ContainsKey(batchId)) - { - return sm_BatchMap[batchId]; - } - return null; - } - - public void AddWidgetToBatchMap(GrabWidget widget, ushort batchId) - { - Debug.Assert(!sm_BatchMap.ContainsKey(batchId)); - sm_BatchMap.Add(batchId, widget); - } - - void Awake() - { - m_Instance = this; - } - - public void Init() - { - m_CameraPathTinter = gameObject.AddComponent(); - - m_GrabWidgets = new List(); - m_ModelWidgets = new List>(); - m_LightWidgets = new List>(); - m_StencilWidgets = new List>(); - m_ImageWidgets = new List>(); - m_VideoWidgets = new List>(); - m_CameraPathWidgets = new List>(); - - m_CanBePinnedWidgets = new List(); - m_CanBeUnpinnedWidgets = new List(); - - m_WidgetsNearBrush = new List(); - m_WidgetsNearWand = new List(); - - m_Home.Init(); - m_Home.SetFixedPosition(Vector3.zero); - m_HomeHintLine = (GameObject)Instantiate(m_HomeHintLinePrefab); - m_HomeHintLineMeshFilter = m_HomeHintLine.GetComponent(); - m_HomeHintLineBaseScale = m_HomeHintLine.transform.localScale; - m_HomeHintLine.transform.parent = transform; - m_HomeHintLine.SetActive(false); - - m_StencilContactInfos = new StencilContactInfo[m_StencilBucketSize]; - m_StencilsDisabled = false; - - FollowingPath = false; - m_CameraPathsVisible = false; - } - - public ModelWidget ModelWidgetPrefab { get { return m_ModelWidgetPrefab; } } - public ImageWidget ImageWidgetPrefab { get { return m_ImageWidgetPrefab; } } - public VideoWidget VideoWidgetPrefab { get { return m_VideoWidgetPrefab; } } - public LightWidget LightWidgetPrefab { get { return m_LightWidgetPrefab; } } - public SceneLightGizmo SceneLightGizmoPrefab { get { return m_SceneLightGizmoPrefab; } } - public CameraPathWidget CameraPathWidgetPrefab { get { return m_CameraPathWidgetPrefab; } } - public GameObject CameraPathPositionKnotPrefab { get { return m_CameraPathPositionKnotPrefab; } } - public GameObject CameraPathRotationKnotPrefab { get { return m_CameraPathRotationKnotPrefab; } } - public GameObject CameraPathSpeedKnotPrefab { get { return m_CameraPathSpeedKnotPrefab; } } - public GameObject CameraPathFovKnotPrefab { get { return m_CameraPathFovKnotPrefab; } } - public GameObject CameraPathKnotSegmentPrefab { get { return m_CameraPathKnotSegmentPrefab; } } - - public IEnumerable ActiveGrabWidgets - { - get - { - if (m_InhibitGrabWhileLoading) - { - // Returns only widgets that are not part of the sketch - return m_GrabWidgets.Where(x => x.m_WidgetObject.activeSelf); - } - return GetAllActiveGrabWidgets(); - } - } - - private IEnumerable GetAllActiveGrabWidgets() - { - for (int i = 0; i < m_GrabWidgets.Count; ++i) - { - if (m_GrabWidgets[i].m_WidgetObject.activeSelf) - { - yield return m_GrabWidgets[i]; - } - } - for (int i = 0; i < m_ModelWidgets.Count; ++i) - { - if (m_ModelWidgets[i].m_WidgetObject.activeSelf) - { - yield return m_ModelWidgets[i]; - } - } - for (int i = 0; i < m_LightWidgets.Count; ++i) - { - if (m_LightWidgets[i].m_WidgetObject.activeSelf) - { - yield return m_LightWidgets[i]; - } - } - for (int i = 0; i < m_StencilWidgets.Count; ++i) - { - if (m_StencilWidgets[i].m_WidgetObject.activeSelf) - { - yield return m_StencilWidgets[i]; - } - } - for (int i = 0; i < m_ImageWidgets.Count; ++i) - { - if (m_ImageWidgets[i].m_WidgetObject.activeSelf) - { - yield return m_ImageWidgets[i]; - } - } - for (int i = 0; i < m_VideoWidgets.Count; ++i) - { - if (m_VideoWidgets[i].m_WidgetObject.activeSelf) - { - yield return m_VideoWidgets[i]; - } - } - for (int i = 0; i < m_CameraPathWidgets.Count; ++i) - { - if (m_CameraPathWidgets[i].m_WidgetObject.activeInHierarchy) - { - yield return m_CameraPathWidgets[i]; - } - } - } - - public IEnumerable MediaWidgets - { - get - { - IEnumerable ret = m_ModelWidgets; - return ret - .Concat(m_ImageWidgets) - .Concat(m_VideoWidgets) - .Concat(m_LightWidgets); - } - } - - public IEnumerable> CameraPathWidgets => - m_CameraPathWidgets.Where(x => x.m_WidgetObject.activeSelf); - - public TypedWidgetData GetCurrentCameraPath() => m_CurrentCameraPath; - - public void SetCurrentCameraPath(CameraPathWidget path) - { - // Early out if we're trying to set the path to the already current path. - if (m_CurrentCameraPath != null && m_CurrentCameraPath.WidgetScript == path) - { - return; - } - - for (int i = 0; i < m_CameraPathWidgets.Count; ++i) - { - if (m_CameraPathWidgets[i].m_WidgetScript == path) - { - FollowingPath = false; - SetCurrentCameraPath_Internal(m_CameraPathWidgets[i]); - App.Switchboard.TriggerCurrentCameraPathChanged(); - return; - } - } - } - - public void ValidateCurrentCameraPath() - { - if (m_CurrentCameraPath == null || - m_CurrentCameraPath.WidgetScript == null || - !m_CurrentCameraPath.m_WidgetObject.activeSelf) - { - var prevPath = m_CurrentCameraPath; - for (int i = 0; i < m_CameraPathWidgets.Count; ++i) - { - if (m_CameraPathWidgets[i] != prevPath && - m_CameraPathWidgets[i].m_WidgetObject.activeSelf) - { - SetCurrentCameraPath_Internal(m_CameraPathWidgets[i]); - return; - } - } - } - } - - void SetCurrentCameraPath_Internal(TypedWidgetData cp) - { - if (m_CurrentCameraPath != null && m_CurrentCameraPath.WidgetScript != null) - { - m_CurrentCameraPath.WidgetScript.SetAsActivePath(false); - } - m_CurrentCameraPath = cp; - if (m_CurrentCameraPath != null && m_CurrentCameraPath.WidgetScript != null) - { - m_CurrentCameraPath.WidgetScript.SetAsActivePath(true); - } - } - - public bool CanRecordCurrentCameraPath() - { - if (SketchSurfacePanel.m_Instance.GetCurrentToolType() != BaseTool.ToolType.MultiCamTool) - { - if (m_CameraPathsVisible && m_CurrentCameraPath != null) - { - CameraPathWidget cpw = m_CurrentCameraPath.WidgetScript; - return (cpw != null) && cpw.gameObject.activeSelf && cpw.Path.NumPositionKnots > 1; - } - } - return false; - } - - // The following methods use indexes to reference camera paths. Because the list of - // camera path widgets can have inactive paths (if they're deleted), these lists may - // have holes. Use caution when using these methods. - // The reason we need these methods is because our UI buttons work with SketchControls - // global commands, which can be modified with generic integer parameters. In those - // cases, we can't pass a CameraPathWidget object. - public CameraPathWidget GetNthActiveCameraPath(int nth) - { - var activeCameraPathWidgets = m_CameraPathWidgets.Where(x => x.m_WidgetObject.activeSelf); - foreach (var cpw in activeCameraPathWidgets) - { - if (nth == 0) - { - return cpw.WidgetScript; - } - --nth; - } - return null; - } - - public bool IsCameraPathAtIndexCurrent(int pathIndex) - { - CameraPathWidget cpw = (m_CurrentCameraPath != null) ? cpw = m_CurrentCameraPath.WidgetScript : - null; - if (cpw == null) { return false; } - return GetNthActiveCameraPath(pathIndex) == m_CurrentCameraPath.WidgetScript; - } - - public int? GetIndexOfCameraPath(CameraPathWidget path) - { - int index = 0; - for (int i = 0; i < m_CameraPathWidgets.Count; ++i) - { - if (m_CameraPathWidgets[i].m_WidgetObject.activeSelf) - { - if (m_CameraPathWidgets[i].WidgetScript == path) - { - return index; - } - ++index; - } - } - return null; - } - - public CameraPathWidget CreatePathWidget() - { - CreateWidgetCommand command = - new CreateWidgetCommand(m_CameraPathWidgetPrefab, TrTransform.identity); - SketchMemoryScript.m_Instance.PerformAndRecordCommand(command); - return m_CameraPathWidgets.Last().WidgetScript; - } - - public bool AnyActivePathHasAKnot() - { - var datas = CameraPathWidgets; - foreach (TypedWidgetData data in datas) - { - if (data.WidgetScript.Path.NumPositionKnots > 0) - { - return true; - } - } - return false; - } - - public void DeleteCameraPath(GrabWidget cameraPathWidgetScript) - { - if (cameraPathWidgetScript != null) - { - // We don't *really* delete it, we just hide it. - SketchMemoryScript.m_Instance.PerformAndRecordCommand( - new HideWidgetCommand(cameraPathWidgetScript)); - FollowingPath = false; - } - - // If our current path is null or inactive, it means we have no camera paths. In that - // instance, if the camera path tool is active, reset back to our default tool. - // I'm doing this because if we leave the camera path tool active, the camera path - // panel shows the button highlighted, which affects the user's flow for being - // invited to start a path. It looks weird. - if (m_CurrentCameraPath == null || !m_CurrentCameraPath.WidgetScript.gameObject.activeSelf) - { - if (SketchSurfacePanel.m_Instance.ActiveToolType == BaseTool.ToolType.CameraPathTool) - { - SketchSurfacePanel.m_Instance.EnableDefaultTool(); - } - } - } - - public bool CameraPathsVisible - { - get { return m_CameraPathsVisible; } - set - { - if (value != m_CameraPathsVisible) - { - m_CameraPathsVisible = value; - - // Camera paths. - for (int i = 0; i < m_CameraPathWidgets.Count; ++i) - { - CameraPathWidget cpw = m_CameraPathWidgets[i].m_WidgetScript as CameraPathWidget; - if (cpw.gameObject.activeSelf) - { - cpw.Path.SetKnotsActive(m_CameraPathsVisible); - } - } - - if (!m_CameraPathsVisible) - { - // Flip back to default tool if we turned off paths. - if (SketchSurfacePanel.m_Instance.ActiveToolType == BaseTool.ToolType.CameraPathTool) - { - SketchSurfacePanel.m_Instance.EnableDefaultTool(); - } - FollowingPath = false; - } - - App.Switchboard.TriggerCameraPathVisibilityChanged(); - } - } - } - - public bool HasSelectableWidgets() - { - return - (m_ModelWidgets.Count > 0) || - (m_LightWidgets.Count > 0) || - (m_ImageWidgets.Count > 0) || - (m_VideoWidgets.Count > 0) || - (!m_StencilsDisabled && m_StencilWidgets.Count > 0); - } - - public bool HasExportableContent(Cloud cloud) - { - switch (cloud) - { - case Cloud.Sketchfab: - return SketchMemoryScript.m_Instance.HasVisibleObjects() || - ExportableModelWidgets.Any(w => w.gameObject.activeSelf) || - ImageWidgets.Any(w => w.gameObject.activeSelf); - default: - return SketchMemoryScript.m_Instance.HasVisibleObjects() || - App.Config.m_EnableReferenceModelExport && - ExportableModelWidgets.Any( - w => w.gameObject.activeSelf && - w.Model.GetLocation().GetLocationType() == Model.Location.Type.PolyAssetId); - } - } - - public bool HasNonExportableContent(Cloud cloud) - { - switch (cloud) - { - case Cloud.Sketchfab: - return VideoWidgets.Any(w => w.gameObject.activeSelf); - default: - return NonExportableModelWidgets.Any(w => w.gameObject.activeSelf) || - ImageWidgets.Any(w => w.gameObject.activeSelf) || - VideoWidgets.Any(w => w.gameObject.activeSelf); - } - } - - public bool StencilsDisabled - { - get { return m_StencilsDisabled; } - set - { - if (value != m_StencilsDisabled) - { - // Flip flag and visuals for all stencils. - for (int i = 0; i < m_StencilWidgets.Count; ++i) - { - StencilWidget sw = m_StencilWidgets[i].WidgetScript; - if (sw) - { - sw.RefreshVisibility(value); - } - } - m_ActiveStencil = null; - } - m_StencilsDisabled = value; - RefreshPinAndUnpinLists(); - } - } - - private static string CanonicalizeForCompare(string path) - { - return path.ToLower().Replace("\\", "/"); - } - - // Shortens full file paths to "Media Library/[Models | Images]/thing" - // Input: absolute path - // Returns: path starting from Media Library/ (e.g. "Media Library/[Models | Images]/thing") - // or null if path does not lead to Media Library - // Throws: ArgumentException if path is not full - public static string GetPathRootedAtMedia(string path) - { - if (!System.IO.Path.IsPathRooted(path)) - { - throw new ArgumentException("Path is not rooted"); - } - var media = App.MediaLibraryPath(); - if (CanonicalizeForCompare(path).StartsWith(CanonicalizeForCompare(media))) - { - return "Media Library" + path.Substring(media.Length); - } - return null; - } - - // Returns path after Media Library/Models for models only - // Input: absolute path - // Returns: path starting after Models/ or null if the path is not to the Models directory - public static string GetModelSubpath(string fullPath) - { - string media = GetPathRootedAtMedia(fullPath); - string modelPath = "Media Library/Models/"; - if (media == null || !media.StartsWith(modelPath)) - { - return null; - } - return media.Substring(modelPath.Length); - } - - // Used only at .tilt-loading time - public void SetDataFromTilt(TiltModels75[] value) - { - m_loadingTiltModels75 = value; - } - - // Used only at .tilt-loading time - public void SetDataFromTilt(TiltImages75[] value) - { - m_loadingTiltImages75 = value; - } - - // Used only at .tilt-loading time - public void SetDataFromTilt(TiltLights[] value) - { - m_loadingTiltLights = value; - } - - public void SetDataFromTilt(CameraPathMetadata[] cameraPaths) - { - for (int i = 0; i < cameraPaths.Length; ++i) - { - CameraPathWidget.CreateFromSaveData(cameraPaths[i]); - } - } - - public void SetDataFromTilt(TiltVideo[] value) - { - m_loadingTiltVideos = value; - } - - public WidgetPinScript GetWidgetPin() - { - GameObject pinObj = Instantiate(m_WidgetPinPrefab); - pinObj.transform.parent = transform; - return pinObj.GetComponent(); - } - - public void DestroyWidgetPin(WidgetPinScript pin) - { - if (pin != null) - { - Destroy(pin.gameObject); - } - } - - // Set the position that widgets can snap to in the current environment - public void SetHomePosition(Vector3 position) - { - m_Home.SetFixedPosition(position); - } - - // Dormant models are still grabbable but visuals/haptics are disabled - public bool WidgetsDormant - { - get { return m_WidgetsDormant; } - set - { - m_WidgetsDormant = value; - Shader.SetGlobalFloat("_WidgetsDormant", value ? 0 : 1); - } - } - - public float WidgetSnapAngle - { - get { return m_WidgetSnapAngle; } - } - - public bool IsOriginHomeWithinSnapRange(Vector3 pos) - { - return m_Home.WithinRange(pos); - } - - public Transform GetHomeXf() - { - return m_Home.transform; - } - - public void SetHomeOwner(Transform owner) - { - m_Home.SetOwner(owner); - m_Home.Reset(); - } - - public void ClearHomeOwner() - { - m_Home.SetOwner(null); - m_Home.gameObject.SetActive(false); - m_HomeHintLine.SetActive(false); - } - - public void EnableHome(bool bEnable) - { - m_Home.gameObject.SetActive(bEnable); - if (!bEnable) - { - m_HomeHintLine.SetActive(false); - } - } - - public void LoadingState(bool bEnter) - { - m_InhibitGrabWhileLoading = bEnter; - } - - public void UpdateHomeHintLine(Vector3 vModelSnapPos) - { - if (!m_Home.WithinRange(vModelSnapPos) && m_Home.WithinHintRange(vModelSnapPos)) - { - // Enable, position, and scale hint line. - m_HomeHintLine.SetActive(true); - Vector3 vHomeToModel = vModelSnapPos - m_Home.transform.position; - m_HomeHintLine.transform.position = m_Home.transform.position + - (vHomeToModel * 0.5f); - m_HomeHintLine.transform.up = vHomeToModel.normalized; - - Vector3 vScale = m_HomeHintLineBaseScale; - vScale.y = vHomeToModel.magnitude * 0.5f; - m_HomeHintLine.transform.localScale = vScale; - - App.Instance.SelectionEffect.RegisterMesh(m_HomeHintLineMeshFilter); - m_Home.RenderHighlight(); - } - else - { - // Disable the line. - m_HomeHintLine.SetActive(false); - } - } - - public bool MagnetizeToStencils(ref Vector3 pos, ref Quaternion rot, IEnumerable stencilsToIgnore = null) - { - // Early out if stencils are disabled. - if (m_StencilsDisabled && !App.UserConfig.Flags.GuideToggleVisiblityOnly) - { - return false; - } - - Vector3 samplePos = pos; - - bool stencilWasUsed = false; - - // If we're painting, we have a different path for magnetization that relies on the - // previous frame. - if (PointerManager.m_Instance.IsLineEnabled()) - { - // If we don't have an active stencil, we're done here. - if (m_ActiveStencil == null) - { - return false; - } - - // Using the 0 index of m_StencilContactInfos as a shortcut. - m_StencilContactInfos[0].widget = m_ActiveStencil; - FindClosestPointOnWidgetSurface(pos, ref m_StencilContactInfos[0]); - - m_ActiveStencil.SetInUse(true); - pos = m_StencilContactInfos[0].pos; - rot = Quaternion.LookRotation(m_StencilContactInfos[0].normal); - stencilWasUsed = true; - } - else - { - StencilWidget prevStencil = m_ActiveStencil; - float fPrevScore = -m_StencilAttachHysteresis; - int iPrevIndex = -1; - m_ActiveStencil = null; - - // Run through the overlap list and find the best stencil to stick to. - int iPrimaryIndex = -1; - float fBestScore = 0; - int sIndex = 0; - - IEnumerable widgetsToCheck = m_StencilWidgets.Select(w => w.WidgetScript); - if (stencilsToIgnore != null) widgetsToCheck = widgetsToCheck.Except(stencilsToIgnore); - foreach (var sw in widgetsToCheck) - { - Debug.Assert(sw != null); - - // Reset tint - sw.SetInUse(false); - - // Does a rough check to see if the stencil might overlap. OverlapSphereNonAlloc is - // shockingly slow, which is why we don't use it. - Collider collider = sw.GrabCollider; - float centerDist = (collider.bounds.center - samplePos).sqrMagnitude; - if (centerDist > - (StencilAttractDist * StencilAttractDist + collider.bounds.extents.sqrMagnitude)) - { - continue; - } - - m_StencilContactInfos[sIndex].widget = sw; - - FindClosestPointOnWidgetSurface(samplePos, ref m_StencilContactInfos[sIndex]); - - // Find out how far we are from this point and save it as a score. - float distToSurfactPoint = (m_StencilContactInfos[sIndex].pos - samplePos).magnitude; - float score = 1.0f - (distToSurfactPoint / StencilAttractDist); - if (score > fBestScore) - { - iPrimaryIndex = sIndex; - fBestScore = score; - m_ActiveStencil = m_StencilContactInfos[sIndex].widget; - } - - if (m_StencilContactInfos[sIndex].widget == prevStencil) - { - fPrevScore = score; - iPrevIndex = sIndex; - } - - if (++sIndex == m_StencilBucketSize) - { - break; - } - } - - // If we are switching between stencils, check to see if we're switching "enough". - if (iPrevIndex != -1 && m_ActiveStencil != null && prevStencil != m_ActiveStencil) - { - if (fPrevScore + m_StencilAttachHysteresis > fBestScore) - { - m_ActiveStencil = prevStencil; - iPrimaryIndex = iPrevIndex; - } - } - - // If we found a good stencil, return the surface collision transform. - if (m_ActiveStencil != null) - { - m_ActiveStencil.SetInUse(true); - pos = m_StencilContactInfos[iPrimaryIndex].pos; - var up = rot * Vector3.up; - rot = Quaternion.LookRotation(m_StencilContactInfos[iPrimaryIndex].normal, up); - stencilWasUsed = true; - } - - if (prevStencil != m_ActiveStencil) - { - PointerManager.m_Instance.DisablePointerPreviewLine(); - } - } - - return stencilWasUsed; - } - - bool FindClosestPointOnCollider( - Ray rRay, Collider collider, out RaycastHit rHitInfo, float fDist) - { - rHitInfo = new RaycastHit(); - return collider.Raycast(rRay, out rHitInfo, fDist); - } - - void FindClosestPointOnWidgetSurface(Vector3 pos, ref StencilContactInfo info) - { - info.widget.FindClosestPointOnSurface(pos, out info.pos, out info.normal); - } - - public bool ShouldUpdateCollisions() - { - return ActiveGrabWidgets.Any(elt => elt.m_WidgetScript.IsCollisionEnabled()); - } - - public IEnumerable ModelWidgets - { - get - { - return m_ModelWidgets - .Select(w => w == null ? null : w.WidgetScript) - .Where(w => w != null); - } - } - - public IEnumerable LightWidgets - { - get - { - return m_LightWidgets - .Select(w => w == null ? null : w.WidgetScript) - .Where(w => w != null); - } - } - - public IEnumerable VideoWidgets - { - get - { - return m_VideoWidgets - .Select(w => w == null ? null : w.WidgetScript) - .Where(w => w != null); - } - } - - public IEnumerable NonExportableModelWidgets - { - get - { - return m_ModelWidgets - .Select(w => w == null ? null : w.WidgetScript) - .Where(w => w != null).Where(w => !w.Model.AllowExport); - } - } - - public IEnumerable ExportableModelWidgets - { - get - { - return m_ModelWidgets - .Select(w => w == null ? null : w.WidgetScript) - .Where(w => w != null).Where(w => w.Model.AllowExport); - } - } - - public IEnumerable StencilWidgets - { - get - { - return m_StencilWidgets - .Select(d => d == null ? null : d.WidgetScript) - .Where(w => w != null); - } - } - - public StencilWidget GetStencilPrefab(StencilType type) - { - for (int i = 0; i < m_StencilMap.Length; ++i) - { - if (m_StencilMap[i].m_Type == type) - { - return m_StencilMap[i].m_StencilPrefab; - } - } - throw new ArgumentException(type.ToString()); - } - - public IEnumerable ImageWidgets - { - get - { - return m_ImageWidgets - .Select(d => d == null ? null : d.m_WidgetScript as ImageWidget) - .Where(w => w != null); - } - } - - public List GetAllUnselectedActiveWidgets() - { - List widgets = new List(); - GetUnselectedActiveWidgetsInList(m_ModelWidgets); - GetUnselectedActiveWidgetsInList(m_LightWidgets); - GetUnselectedActiveWidgetsInList(m_ImageWidgets); - GetUnselectedActiveWidgetsInList(m_VideoWidgets); - if (!m_StencilsDisabled) - { - GetUnselectedActiveWidgetsInList(m_StencilWidgets); - } - return widgets; - - void GetUnselectedActiveWidgetsInList(List> list) where T : GrabWidget - { - for (int i = 0; i < list.Count; ++i) - { - GrabWidget w = list[i].m_WidgetScript; - if (!w.Pinned && w.transform.parent == App.Scene.ActiveCanvas.transform && - w.gameObject.activeSelf) - { - widgets.Add(w); - } - } - } - } - - public void RefreshPinAndUnpinLists() - { - if (RefreshPinAndUnpinAction != null) - { - m_CanBePinnedWidgets.Clear(); - m_CanBeUnpinnedWidgets.Clear(); - - RefreshPinUnpinWidgetList(m_ModelWidgets); - RefreshPinUnpinWidgetList(m_LightWidgets); - RefreshPinUnpinWidgetList(m_ImageWidgets); - RefreshPinUnpinWidgetList(m_VideoWidgets); - RefreshPinUnpinWidgetList(m_StencilWidgets); - - RefreshPinAndUnpinAction(); - } - - // New in C# 7 - local functions! - void RefreshPinUnpinWidgetList(List> widgetList) where T : GrabWidget - { - foreach (var widgetData in widgetList) - { - var widget = widgetData.WidgetScript; - if (widget.gameObject.activeSelf && widget.AllowPinning) - { - if (widget.Pinned) - { - m_CanBeUnpinnedWidgets.Add(widget); - } - else - { - m_CanBePinnedWidgets.Add(widget); - } - } - } - } - } - - public void RegisterHighlightsForPinnableWidgets(bool pinnable) - { - List widgets = pinnable ? m_CanBePinnedWidgets : m_CanBeUnpinnedWidgets; - for (int i = 0; i < widgets.Count; ++i) - { - GrabWidget w = widgets[i]; - // If stencils are disabled, don't highlight them, cause we can interact with 'em. - if (WidgetManager.m_Instance.StencilsDisabled) - { - if (w is StencilWidget) - { - continue; - } - } - w.RegisterHighlight(); - } - } - - public void RegisterGrabWidget(GameObject rWidget) - { - // Find b/29514616 - if (ReferenceEquals(rWidget, null)) - { - throw new ArgumentNullException("rWidget"); - } - else if (rWidget == null) - { - throw new ArgumentNullException("rWidget(2)"); - } - GrabWidget generic = rWidget.GetComponent(); - if (generic == null) - { - throw new InvalidOperationException($"Object {rWidget.name} is not a GrabWidget"); - } - - if (generic is ModelWidget mw) - { - m_ModelWidgets.Add(new TypedWidgetData(mw)); - } - else if (generic is LightWidget light) - { - m_LightWidgets.Add(new TypedWidgetData(light)); - } - else if (generic is StencilWidget stencil) - { - m_StencilWidgets.Add(new TypedWidgetData(stencil)); - } - else if (generic is ImageWidget image) - { - m_ImageWidgets.Add(new TypedWidgetData(image)); - } - else if (generic is VideoWidget video) - { - m_VideoWidgets.Add(new TypedWidgetData(video)); - } - else if (generic is CameraPathWidget cpw) - { - m_CameraPathWidgets.Add(new TypedWidgetData(cpw)); - } - else - { - m_GrabWidgets.Add(new GrabWidgetData(generic)); - } - - RefreshPinAndUnpinLists(); - } - - // Returns true if a widget was removed - static bool RemoveFrom(List list, GameObject rWidget) - where T : GrabWidgetData - { - int idx = list.FindIndex((data) => data.m_WidgetObject == rWidget); - if (idx != -1) - { - list.RemoveAt(idx); - return true; - } - return false; - } - - public void UnregisterGrabWidget(GameObject rWidget) - { - // Get this widget's batchId out of the map. - sm_BatchMap.Remove(rWidget.GetComponent().BatchId); - - // Pull out of pin tool lists. - RefreshPinAndUnpinLists(); - - // Decrement model vert count if we're a model widget. - ModelWidget mw = rWidget.GetComponent() as ModelWidget; - if (mw != null) - { - m_ModelVertCount -= mw.NumVertsTrackedByWidgetManager; - } - // Same with image widget. - ImageWidget iw = rWidget.GetComponent() as ImageWidget; - if (iw != null) - { - m_ImageVertCount -= iw.NumVertsTrackedByWidgetManager; - } - - if (RemoveFrom(m_ModelWidgets, rWidget)) { return; } - if (RemoveFrom(m_LightWidgets, rWidget)) { return; } - if (RemoveFrom(m_StencilWidgets, rWidget)) { return; } - if (RemoveFrom(m_ImageWidgets, rWidget)) { return; } - if (RemoveFrom(m_VideoWidgets, rWidget)) { return; } - if (RemoveFrom(m_CameraPathWidgets, rWidget)) { return; } - RemoveFrom(m_GrabWidgets, rWidget); - } - - public ImageWidget GetNearestImage(Vector3 pos, float maxDepth, ref Vector3 sampleLoc) - { - ImageWidget bestImage = null; - float leastDistance = float.MaxValue; - foreach (var im in ImageWidgets.Where(i => i.gameObject.activeSelf)) - { - Vector3 dropper_QS; - Vector3 dropper_GS = pos; - Matrix4x4 xfQuadFromGlobal = im.m_ImageQuad.transform.worldToLocalMatrix; - dropper_QS = xfQuadFromGlobal.MultiplyPoint3x4(dropper_GS); - if (Mathf.Abs(dropper_QS.z) < leastDistance - && Mathf.Abs(dropper_QS.x) <= 0.5f - && Mathf.Abs(dropper_QS.y) <= 0.5f - && Mathf.Abs(dropper_QS.z) <= maxDepth / Mathf.Abs(im.GetSignedWidgetSize())) - { - bestImage = im; - leastDistance = Mathf.Abs(dropper_QS.z); - sampleLoc = dropper_QS; - } - } - return bestImage; - } - - public void RefreshNearestWidgetLists(Ray currentGazeRay, int currentGazeObject) - { - m_WidgetsNearBrush.Clear(); - UpdateNearestGrabsFor(InputManager.ControllerName.Brush, currentGazeRay, currentGazeObject); - foreach (GrabWidgetData widget in ActiveGrabWidgets) - { - if (widget.m_NearController) - { - // Deep copy. - m_WidgetsNearBrush.Add(widget.Clone()); - } - } - - m_WidgetsNearWand.Clear(); - UpdateNearestGrabsFor(InputManager.ControllerName.Wand, currentGazeRay, currentGazeObject); - foreach (GrabWidgetData widget in ActiveGrabWidgets) - { - if (widget.m_NearController) - { - m_WidgetsNearWand.Add(widget.Clone()); - } - } - } - - // Helper for RefreshNearestWidgetLists - void UpdateNearestGrabsFor( - InputManager.ControllerName name, Ray currentGazeRay, int currentGazeObject) - { - // Reset hit flags. - foreach (var elt in ActiveGrabWidgets) - { - elt.m_NearController = false; - elt.m_ControllerScore = -1.0f; - } - - Vector3 controllerPos = Vector3.zero; - if (name == InputManager.ControllerName.Brush) - { - controllerPos = InputManager.m_Instance.GetBrushControllerAttachPoint().position; - } - else if (name == InputManager.ControllerName.Wand) - { - controllerPos = InputManager.m_Instance.GetWandControllerAttachPoint().position; - } - else - { - Debug.LogError("UpdateNearestGrabsFor() only supports Brush and Wand controller types."); - } - - // Figure out if controller is in view frustum. If it isn't, don't allow widget grabs. - Vector3 vToController = controllerPos - currentGazeRay.origin; - vToController.Normalize(); - if (Vector3.Angle(vToController, currentGazeRay.direction) > m_GazeMaxAngleFromFacing) - { - return; - } - - BasePanel gazePanel = null; - if (currentGazeObject > -1) - { - gazePanel = PanelManager.m_Instance.GetPanel(currentGazeObject); - } - - foreach (var data in ActiveGrabWidgets) - { - if (!data.m_WidgetScript.enabled) - { - continue; - } - if (m_StencilsDisabled && data.m_WidgetScript is StencilWidget) - { - continue; - } - if (SelectionManager.m_Instance.ShouldRemoveFromSelection() && - !data.m_WidgetScript.CanGrabDuringDeselection()) - { - continue; - } - if (SelectionManager.m_Instance.IsWidgetSelected(data.m_WidgetScript)) - { - continue; - } - float score = data.m_WidgetScript.GetActivationScore(controllerPos, name); - if (score < m_PanelFocusActivationScore && name == InputManager.ControllerName.Brush && - gazePanel && data.m_WidgetObject == gazePanel.gameObject) - { - // If the brush is pointing at a panel, make sure that the panel will be the widget grabbed - score = m_PanelFocusActivationScore; - } - if (score < 0) - { - continue; - } - - data.m_NearController = true; - data.m_ControllerScore = score; - } - } - - public float DistanceToNearestWidget(Ray ray) - { - // If we're in controller mode, find the nearest colliding widget that might get in our way. - float fNearestWidget = 99999.0f; - foreach (var elt in ActiveGrabWidgets) - { - float fWidgetDist = 0.0f; - if (elt.m_WidgetScript.DistanceToCollider(ray, out fWidgetDist)) - { - fNearestWidget = Mathf.Min(fNearestWidget, fWidgetDist); - } - } - return fNearestWidget; - } - - public void DestroyAllWidgets() - { - DestroyWidgetList(m_ModelWidgets); - DestroyWidgetList(m_LightWidgets); - DestroyWidgetList(m_ImageWidgets); - DestroyWidgetList(m_VideoWidgets); - DestroyWidgetList(m_StencilWidgets); - DestroyWidgetList(m_CameraPathWidgets, false); - SetCurrentCameraPath_Internal(null); - App.Switchboard.TriggerAllWidgetsDestroyed(); - - void DestroyWidgetList(List> widgetList, - bool hideBeforeDestroy = true) where T : GrabWidget - { - while (widgetList.Count > 0) - { - GrabWidget widget = widgetList[0].m_WidgetScript; - GameObject obj = widgetList[0].m_WidgetObject; - if (hideBeforeDestroy) { widget.Hide(); } - widget.OnPreDestroy(); - UnregisterGrabWidget(obj); - Destroy(obj); - } - } - } - - /// Upon return: - /// - ImageWidgets have at least an icon-sized Texture2D; it will be mutated with - /// the fullres texture data some time later. - /// - ModelWidgets may have a dummy, invisible Model instead of the actual Model they want; - /// the Model will be automatically replaced with the loaded Model some time later. - public IEnumerator CreateMediaWidgetsFromLoadDataCoroutine() - { - if (m_loadingTiltModels75 != null) - { - OverlayManager.m_Instance.RefuseProgressBarChanges(true); - - if (App.Config.kModelWidgetsWaitForLoad) - { - var assetIds = m_loadingTiltModels75 - .Select(tm => tm.AssetId).Where(aid => aid != null).ToArray(); - // Kick off a bunch of loads... - foreach (var assetId in assetIds) - { - if (App.PolyAssetCatalog.GetAssetLoadState(assetId) - != PolyAssetCatalog.AssetLoadState.Loaded) - { - App.PolyAssetCatalog.RequestModelLoad(assetId, "tiltload"); - } - } - // ... and wait for them to complete - // No widgets have been created yet, so we can't use AreMediaWidgetsStillLoading. - bool IsLoading(string assetId) - { - var state = App.PolyAssetCatalog.GetAssetLoadState(assetId); - return (state == PolyAssetCatalog.AssetLoadState.Downloading || - state == PolyAssetCatalog.AssetLoadState.Loading); - } - while (assetIds.Any(IsLoading)) - { - yield return null; - } - } - - for (int i = 0; i < m_loadingTiltModels75.Length; i++) - { - ModelWidget.CreateFromSaveData(m_loadingTiltModels75[i]); - OverlayManager.m_Instance.UpdateProgress( - (float)(i + 1) / m_loadingTiltModels75.Length, true); - } - OverlayManager.m_Instance.RefuseProgressBarChanges(false); - m_loadingTiltModels75 = null; - } - ModelCatalog.m_Instance.PrintMissingModelWarnings(); - if (m_loadingTiltLights != null) - { - foreach (var light in m_loadingTiltLights) - { - LightWidget.FromTiltLight(light); - } - m_loadingTiltLights = null; - } - if (m_loadingTiltImages75 != null) - { - foreach (TiltImages75 import in m_loadingTiltImages75) - { - // TODO: FromTiltImage should take advantage of being called by a coroutine - // so it can avoid calling ReferenceImage.SynchronousLoad() - ImageWidget.FromTiltImage(import); - } - m_loadingTiltImages75 = null; - } - if (m_loadingTiltVideos != null) - { - foreach (var video in m_loadingTiltVideos) - { - VideoWidget.FromTiltVideo(video); - } - m_loadingTiltVideos = null; - } - yield break; - } - - /// Returns true when all media widgets have finished getting created. - /// Note that: - /// - ImageWidgets may have low-res textures - /// - ModelWidgets may not have a model yet (depending on Config.kModelWidgetsWaitForLoad) - public bool CreatingMediaWidgets => - m_loadingTiltModels75 != null || - m_loadingTiltImages75 != null || - m_loadingTiltVideos != null; - - /// Returns true if any widgets are still waiting for their data. - public bool AreMediaWidgetsStillLoading() - { - if (CreatingMediaWidgets) { return true; } - // Widgets have been created, but some may not have their data yet - PolyAssetCatalog pac = App.PolyAssetCatalog; - foreach (var gwd in m_ModelWidgets) - { - Model.Location loc = gwd.WidgetScript.Model.GetLocation(); - if (loc.GetLocationType() == Model.Location.Type.PolyAssetId) - { - switch (pac.GetAssetLoadState(loc.AssetId)) - { - case PolyAssetCatalog.AssetLoadState.Downloading: - case PolyAssetCatalog.AssetLoadState.Loading: - return true; - } - } - } - return false; - } - - // Smaller is better. Invalid objects get negative values. - static float ScoreByAngleAndDistance(GrabWidgetData data) - { - if (!data.m_WidgetScript.Showing) { return -1; } - Transform source = ViewpointScript.Head; - Transform dest = data.m_WidgetObject.transform; - Vector3 delta = (dest.position - source.position); - float dist = delta.magnitude; - return dist / Vector3.Dot(delta.normalized, source.forward); - } - - // Simulate a grab and toss. Use for debugging in monoscopic only. - public void TossNearestWidget() - { - var widget = MediaWidgets.Where(w => w.m_WidgetScript.Showing) - .Select(w => new { score = ScoreByAngleAndDistance(w), widget = w.m_WidgetScript }) - .Where(data => data.score > 0) - .OrderBy(data => data.score) - .FirstOrDefault().widget; - - if (widget != null) - { - if (widget.Pinned) - { - SketchMemoryScript.m_Instance.PerformAndRecordCommand(new PinWidgetCommand(widget, false)); - } - // All media widgets record their movements. - SketchMemoryScript.m_Instance.PerformAndRecordCommand( - new MoveWidgetCommand(widget, widget.LocalTransform, widget.CustomDimension)); - float speed = (App.METERS_TO_UNITS * SketchControlsScript.m_Instance.m_TossThresholdMeters); - Vector3 vLinVel = ViewpointScript.Head.forward * speed; - Vector3 vAngVel = Quaternion.AngleAxis(UnityEngine.Random.Range(0, 360), Vector3.forward) - * ViewpointScript.Head.up * 500; - widget.SetVelocities(vLinVel, vAngVel, widget.transform.position); - } - else - { - Debug.Log("No media in sketch"); - } - } - - public List> ActiveImageWidgets => - m_ImageWidgets.Where(w => w.WidgetScript.gameObject.activeSelf).ToList(); - public List> ActiveLightWidgets => - m_LightWidgets.Where(w => w.WidgetScript.gameObject.activeSelf).ToList(); - public List> ActiveModelWidgets => - m_ModelWidgets.Where(w => w.WidgetScript.gameObject.activeSelf).ToList(); - public List> ActiveVideoWidgets => - m_VideoWidgets.Where(w => w.WidgetScript.gameObject.activeSelf).ToList(); - public List> ActiveCameraPathWidgets => - m_CameraPathWidgets.Where(w => w.WidgetScript.gameObject.activeSelf).ToList(); - - } -} +//// Copyright 2020 The Tilt Brush Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// 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.Linq; +using System.Collections.Generic; +using UnityEngine; + +namespace TiltBrush +{ + + // These names are used in our save format, so they must be protected from obfuscation + // Do not change the names of any of them, unless they've never been released. + [Serializable] + public enum StencilType + { + Plane, + Cube, + Sphere, + Capsule, + Cone, + Cylinder, + InteriorDome, + Pyramid, + Ellipsoid + } + + [Serializable] + public struct StencilMapKey + { + public StencilType m_Type; + public StencilWidget m_StencilPrefab; + } + + public struct StencilContactInfo + { + public StencilWidget widget; + public Vector3 pos; + public Vector3 normal; + } + + public class GrabWidgetData + { + public readonly GameObject m_WidgetObject; + public readonly GrabWidget m_WidgetScript; + + // These fields are only valid during a call to GetNearestGrabWidget, + // and are undefined afterwards. Do not use them. + + public bool m_NearController; + // only valid if m_NearController == true + public float m_ControllerScore; + + public GrabWidgetData(GrabWidget widget) + { + m_WidgetScript = widget; + m_WidgetObject = widget.gameObject; + } + // Could maybe get by without this since all users of Clone() don't care if they + // receive a plain old GrabWidgetData or not. + public virtual GrabWidgetData Clone() + { + return new GrabWidgetData(m_WidgetScript) + { + m_NearController = m_NearController, + m_ControllerScore = m_ControllerScore + }; + } + } + + public class TypedWidgetData : GrabWidgetData where T : GrabWidget + { + private readonly T m_typedWidget; + public new T WidgetScript => m_typedWidget; + public TypedWidgetData(T widget) : base(widget) + { + m_typedWidget = widget; + } + public override GrabWidgetData Clone() + { + return new TypedWidgetData(m_typedWidget) + { + m_NearController = m_NearController, + m_ControllerScore = m_ControllerScore + }; + } + } + + public class WidgetManager : MonoBehaviour + { + static public WidgetManager m_Instance; + + [SerializeField] ModelWidget m_ModelWidgetPrefab; + [SerializeField] GameObject m_WidgetPinPrefab; + [SerializeField] ImageWidget m_ImageWidgetPrefab; + [SerializeField] VideoWidget m_VideoWidgetPrefab; + [SerializeField] LightWidget m_LightWidgetPrefab; + [SerializeField] SceneLightGizmo m_SceneLightGizmoPrefab; + [SerializeField] CameraPathWidget m_CameraPathWidgetPrefab; + [SerializeField] private GameObject m_CameraPathPositionKnotPrefab; + [SerializeField] private GameObject m_CameraPathRotationKnotPrefab; + [SerializeField] private GameObject m_CameraPathSpeedKnotPrefab; + [SerializeField] private GameObject m_CameraPathFovKnotPrefab; + [SerializeField] private GameObject m_CameraPathKnotSegmentPrefab; + [SerializeField] private GrabWidgetHome m_Home; + [SerializeField] private GameObject m_HomeHintLinePrefab; + [SerializeField] float m_WidgetSnapAngle = 15.0f; + [SerializeField] float m_GazeMaxAngleFromFacing = 70.0f; + [SerializeField] private float m_PanelFocusActivationScore; + [SerializeField] private float m_ModelVertCountScalar = 1.0f; + + [Header("Stencils")] + [SerializeField] StencilMapKey[] m_StencilMap; + [SerializeField] private float m_StencilAttractDist = 0.5f; + [SerializeField] private float m_StencilAttachHysteresis = 0.1f; + [SerializeField] private string m_StencilLayerName; + [SerializeField] private string m_PinnedStencilLayerName; + + private bool m_WidgetsDormant; + private bool m_InhibitGrabWhileLoading; + + private GameObject m_HomeHintLine; + private MeshFilter m_HomeHintLineMeshFilter; + private Vector3 m_HomeHintLineBaseScale; + + private StencilContactInfo[] m_StencilContactInfos; + private const int m_StencilBucketSize = 16; + private StencilWidget m_ActiveStencil; + private bool m_StencilsDisabled; + + // All grabbable widgets should be in exactly one of these lists. + // Widgets will be in the most specific list. + private List m_GrabWidgets; + private List> m_ModelWidgets; + private List> m_LightWidgets; + private List> m_StencilWidgets; + private List> m_ImageWidgets; + private List> m_VideoWidgets; + private List> m_CameraPathWidgets; + + // These lists are used by the PinTool. They're kept in sync by the + // widget manager, but the PinTool is responsible for their coherency. + private List m_CanBePinnedWidgets; + private List m_CanBeUnpinnedWidgets; + public event Action RefreshPinAndUnpinAction; + + private TiltModels75[] m_loadingTiltModels75; + private TiltLights[] m_loadingTiltLights; + private TiltImages75[] m_loadingTiltImages75; + private TiltVideo[] m_loadingTiltVideos; + + private List m_WidgetsNearBrush; + private List m_WidgetsNearWand; + + // This value is used by SketchMemoryScript to check the sketch against memory limits. + // It's incremented when a model is registered, and decremented when a model is + // unregistered. + private int m_ModelVertCount; + // Similar to above, this value is used to check against memory limits. Images are always + // the same number of verts, however, so this number is scaled by texture size. It's a + // hand-wavey calculation. + private int m_ImageVertCount; + + // Camera path. + [NonSerialized] public bool FollowingPath; + private TypedWidgetData m_CurrentCameraPath; + private bool m_CameraPathsVisible; + private CameraPathTinter m_CameraPathTinter; + + static private Dictionary sm_BatchMap = new Dictionary(); + public bool m_EnableSnapToGuides; + + public StencilWidget ActiveStencil + { + get { return m_ActiveStencil; } + } + + public void ResetActiveStencil() + { + m_ActiveStencil = null; + } + + public int StencilLayerIndex + { + get { return LayerMask.NameToLayer(m_StencilLayerName); } + } + + public int PinnedStencilLayerIndex + { + get { return LayerMask.NameToLayer(m_PinnedStencilLayerName); } + } + + public LayerMask PinnedStencilLayerMask + { + get { return LayerMask.GetMask(m_PinnedStencilLayerName); } + } + + public LayerMask StencilLayerMask + { + get { return LayerMask.GetMask(m_StencilLayerName); } + } + + public float StencilAttractDist + { + get => m_StencilAttractDist; + set + { + m_StencilAttractDist = value; + App.Switchboard.TriggerStencilAttractDistChanged(); + } + } + + public List WidgetsNearBrush + { + get { return m_WidgetsNearBrush; } + } + + public List WidgetsNearWand + { + get { return m_WidgetsNearWand; } + } + + public bool AnyWidgetsToPin + { + get { return m_CanBePinnedWidgets.Count > 0; } + } + + public bool AnyWidgetsToUnpin + { + get { return m_CanBeUnpinnedWidgets.Count > 0; } + } + + public float ModelVertCountScalar + { + get { return m_ModelVertCountScalar; } + } + + public int ImageVertCount + { + get { return m_ImageVertCount; } + } + + public void AdjustModelVertCount(int amount) + { + m_ModelVertCount += amount; + } + + public void AdjustImageVertCount(int amount) + { + m_ImageVertCount += amount; + } + + public int WidgetsVertCount + { + get { return m_ModelVertCount + m_ImageVertCount; } + } + + public bool AnyVideoWidgetActive => m_VideoWidgets.Any(x => x.m_WidgetObject.activeSelf); + + public bool AnyCameraPathWidgetsActive => + m_CameraPathWidgets.Any(x => x.m_WidgetObject.activeSelf); + + public CameraPathTinter PathTinter { get => m_CameraPathTinter; } + + // Returns the associated widget for the given batchId. + // Returns null if key doesn't exist. + public GrabWidget GetBatch(ushort batchId) + { + if (sm_BatchMap.ContainsKey(batchId)) + { + return sm_BatchMap[batchId]; + } + return null; + } + + public void AddWidgetToBatchMap(GrabWidget widget, ushort batchId) + { + Debug.Assert(!sm_BatchMap.ContainsKey(batchId)); + sm_BatchMap.Add(batchId, widget); + } + + void Awake() + { + m_Instance = this; + } + + public void Init() + { + m_CameraPathTinter = gameObject.AddComponent(); + + m_GrabWidgets = new List(); + m_ModelWidgets = new List>(); + m_LightWidgets = new List>(); + m_StencilWidgets = new List>(); + m_ImageWidgets = new List>(); + m_VideoWidgets = new List>(); + m_CameraPathWidgets = new List>(); + + m_CanBePinnedWidgets = new List(); + m_CanBeUnpinnedWidgets = new List(); + + m_WidgetsNearBrush = new List(); + m_WidgetsNearWand = new List(); + + m_Home.Init(); + m_Home.SetFixedPosition(Vector3.zero); + m_HomeHintLine = (GameObject)Instantiate(m_HomeHintLinePrefab); + m_HomeHintLineMeshFilter = m_HomeHintLine.GetComponent(); + m_HomeHintLineBaseScale = m_HomeHintLine.transform.localScale; + m_HomeHintLine.transform.parent = transform; + m_HomeHintLine.SetActive(false); + + m_StencilContactInfos = new StencilContactInfo[m_StencilBucketSize]; + m_StencilsDisabled = false; + + FollowingPath = false; + m_CameraPathsVisible = false; + } + + public ModelWidget ModelWidgetPrefab { get { return m_ModelWidgetPrefab; } } + public ImageWidget ImageWidgetPrefab { get { return m_ImageWidgetPrefab; } } + public VideoWidget VideoWidgetPrefab { get { return m_VideoWidgetPrefab; } } + public LightWidget LightWidgetPrefab { get { return m_LightWidgetPrefab; } } + public SceneLightGizmo SceneLightGizmoPrefab { get { return m_SceneLightGizmoPrefab; } } + public CameraPathWidget CameraPathWidgetPrefab { get { return m_CameraPathWidgetPrefab; } } + public GameObject CameraPathPositionKnotPrefab { get { return m_CameraPathPositionKnotPrefab; } } + public GameObject CameraPathRotationKnotPrefab { get { return m_CameraPathRotationKnotPrefab; } } + public GameObject CameraPathSpeedKnotPrefab { get { return m_CameraPathSpeedKnotPrefab; } } + public GameObject CameraPathFovKnotPrefab { get { return m_CameraPathFovKnotPrefab; } } + public GameObject CameraPathKnotSegmentPrefab { get { return m_CameraPathKnotSegmentPrefab; } } + + public IEnumerable ActiveGrabWidgets + { + get + { + if (m_InhibitGrabWhileLoading) + { + // Returns only widgets that are not part of the sketch + return m_GrabWidgets.Where(x => x.m_WidgetObject.activeSelf); + } + return GetAllActiveGrabWidgets(); + } + } + + private IEnumerable GetAllActiveGrabWidgets() + { + for (int i = 0; i < m_GrabWidgets.Count; ++i) + { + if (m_GrabWidgets[i].m_WidgetObject.activeSelf) + { + yield return m_GrabWidgets[i]; + } + } + for (int i = 0; i < m_ModelWidgets.Count; ++i) + { + if (m_ModelWidgets[i].m_WidgetObject.activeSelf) + { + yield return m_ModelWidgets[i]; + } + } + for (int i = 0; i < m_LightWidgets.Count; ++i) + { + if (m_LightWidgets[i].m_WidgetObject.activeSelf) + { + yield return m_LightWidgets[i]; + } + } + for (int i = 0; i < m_StencilWidgets.Count; ++i) + { + if (m_StencilWidgets[i].m_WidgetObject.activeSelf) + { + yield return m_StencilWidgets[i]; + } + } + for (int i = 0; i < m_ImageWidgets.Count; ++i) + { + if (m_ImageWidgets[i].m_WidgetObject.activeSelf) + { + yield return m_ImageWidgets[i]; + } + } + for (int i = 0; i < m_VideoWidgets.Count; ++i) + { + if (m_VideoWidgets[i].m_WidgetObject.activeSelf) + { + yield return m_VideoWidgets[i]; + } + } + for (int i = 0; i < m_CameraPathWidgets.Count; ++i) + { + if (m_CameraPathWidgets[i].m_WidgetObject.activeInHierarchy) + { + yield return m_CameraPathWidgets[i]; + } + } + } + + public IEnumerable MediaWidgets + { + get + { + IEnumerable ret = m_ModelWidgets; + return ret + .Concat(m_ImageWidgets) + .Concat(m_VideoWidgets) + .Concat(m_LightWidgets); + } + } + + public IEnumerable> CameraPathWidgets => + m_CameraPathWidgets.Where(x => x.m_WidgetObject.activeSelf); + + public TypedWidgetData GetCurrentCameraPath() => m_CurrentCameraPath; + + public void SetCurrentCameraPath(CameraPathWidget path) + { + // Early out if we're trying to set the path to the already current path. + if (m_CurrentCameraPath != null && m_CurrentCameraPath.WidgetScript == path) + { + return; + } + + for (int i = 0; i < m_CameraPathWidgets.Count; ++i) + { + if (m_CameraPathWidgets[i].m_WidgetScript == path) + { + FollowingPath = false; + SetCurrentCameraPath_Internal(m_CameraPathWidgets[i]); + App.Switchboard.TriggerCurrentCameraPathChanged(); + return; + } + } + } + + public void ValidateCurrentCameraPath() + { + if (m_CurrentCameraPath == null || + m_CurrentCameraPath.WidgetScript == null || + !m_CurrentCameraPath.m_WidgetObject.activeSelf) + { + var prevPath = m_CurrentCameraPath; + for (int i = 0; i < m_CameraPathWidgets.Count; ++i) + { + if (m_CameraPathWidgets[i] != prevPath && + m_CameraPathWidgets[i].m_WidgetObject.activeSelf) + { + SetCurrentCameraPath_Internal(m_CameraPathWidgets[i]); + return; + } + } + } + } + + void SetCurrentCameraPath_Internal(TypedWidgetData cp) + { + if (m_CurrentCameraPath != null && m_CurrentCameraPath.WidgetScript != null) + { + m_CurrentCameraPath.WidgetScript.SetAsActivePath(false); + } + m_CurrentCameraPath = cp; + if (m_CurrentCameraPath != null && m_CurrentCameraPath.WidgetScript != null) + { + m_CurrentCameraPath.WidgetScript.SetAsActivePath(true); + } + } + + public bool CanRecordCurrentCameraPath() + { + if (SketchSurfacePanel.m_Instance.GetCurrentToolType() != BaseTool.ToolType.MultiCamTool) + { + if (m_CameraPathsVisible && m_CurrentCameraPath != null) + { + CameraPathWidget cpw = m_CurrentCameraPath.WidgetScript; + return (cpw != null) && cpw.gameObject.activeSelf && cpw.Path.NumPositionKnots > 1; + } + } + return false; + } + + // The following methods use indexes to reference camera paths. Because the list of + // camera path widgets can have inactive paths (if they're deleted), these lists may + // have holes. Use caution when using these methods. + // The reason we need these methods is because our UI buttons work with SketchControls + // global commands, which can be modified with generic integer parameters. In those + // cases, we can't pass a CameraPathWidget object. + public CameraPathWidget GetNthActiveCameraPath(int nth) + { + var activeCameraPathWidgets = m_CameraPathWidgets.Where(x => x.m_WidgetObject.activeSelf); + foreach (var cpw in activeCameraPathWidgets) + { + if (nth == 0) + { + return cpw.WidgetScript; + } + --nth; + } + return null; + } + + public bool IsCameraPathAtIndexCurrent(int pathIndex) + { + CameraPathWidget cpw = (m_CurrentCameraPath != null) ? cpw = m_CurrentCameraPath.WidgetScript : + null; + if (cpw == null) { return false; } + return GetNthActiveCameraPath(pathIndex) == m_CurrentCameraPath.WidgetScript; + } + + public int? GetIndexOfCameraPath(CameraPathWidget path) + { + int index = 0; + for (int i = 0; i < m_CameraPathWidgets.Count; ++i) + { + if (m_CameraPathWidgets[i].m_WidgetObject.activeSelf) + { + if (m_CameraPathWidgets[i].WidgetScript == path) + { + return index; + } + ++index; + } + } + return null; + } + + public CameraPathWidget CreatePathWidget() + { + CreateWidgetCommand command = + new CreateWidgetCommand(m_CameraPathWidgetPrefab, TrTransform.identity); + SketchMemoryScript.m_Instance.PerformAndRecordCommand(command); + return m_CameraPathWidgets.Last().WidgetScript; + } + + public bool AnyActivePathHasAKnot() + { + var datas = CameraPathWidgets; + foreach (TypedWidgetData data in datas) + { + if (data.WidgetScript.Path.NumPositionKnots > 0) + { + return true; + } + } + return false; + } + + public void DeleteCameraPath(GrabWidget cameraPathWidgetScript) + { + if (cameraPathWidgetScript != null) + { + // We don't *really* delete it, we just hide it. + SketchMemoryScript.m_Instance.PerformAndRecordCommand( + new HideWidgetCommand(cameraPathWidgetScript)); + FollowingPath = false; + } + + // If our current path is null or inactive, it means we have no camera paths. In that + // instance, if the camera path tool is active, reset back to our default tool. + // I'm doing this because if we leave the camera path tool active, the camera path + // panel shows the button highlighted, which affects the user's flow for being + // invited to start a path. It looks weird. + if (m_CurrentCameraPath == null || !m_CurrentCameraPath.WidgetScript.gameObject.activeSelf) + { + if (SketchSurfacePanel.m_Instance.ActiveToolType == BaseTool.ToolType.CameraPathTool) + { + SketchSurfacePanel.m_Instance.EnableDefaultTool(); + } + } + } + + public bool CameraPathsVisible + { + get { return m_CameraPathsVisible; } + set + { + if (value != m_CameraPathsVisible) + { + m_CameraPathsVisible = value; + + // Camera paths. + for (int i = 0; i < m_CameraPathWidgets.Count; ++i) + { + CameraPathWidget cpw = m_CameraPathWidgets[i].m_WidgetScript as CameraPathWidget; + if (cpw.gameObject.activeSelf) + { + cpw.Path.SetKnotsActive(m_CameraPathsVisible); + } + } + + if (!m_CameraPathsVisible) + { + // Flip back to default tool if we turned off paths. + if (SketchSurfacePanel.m_Instance.ActiveToolType == BaseTool.ToolType.CameraPathTool) + { + SketchSurfacePanel.m_Instance.EnableDefaultTool(); + } + FollowingPath = false; + } + + App.Switchboard.TriggerCameraPathVisibilityChanged(); + } + } + } + + public bool HasSelectableWidgets() + { + return + (m_ModelWidgets.Count > 0) || + (m_LightWidgets.Count > 0) || + (m_ImageWidgets.Count > 0) || + (m_VideoWidgets.Count > 0) || + (!m_StencilsDisabled && m_StencilWidgets.Count > 0); + } + + public bool HasExportableContent(Cloud cloud) + { + switch (cloud) + { + case Cloud.Sketchfab: + return SketchMemoryScript.m_Instance.HasVisibleObjects() || + ExportableModelWidgets.Any(w => w.gameObject.activeSelf) || + ImageWidgets.Any(w => w.gameObject.activeSelf); + default: + return SketchMemoryScript.m_Instance.HasVisibleObjects() || + App.Config.m_EnableReferenceModelExport && + ExportableModelWidgets.Any( + w => w.gameObject.activeSelf && + w.Model.GetLocation().GetLocationType() == Model.Location.Type.IcosaAssetId); + } + } + + public bool HasNonExportableContent(Cloud cloud) + { + switch (cloud) + { + case Cloud.Sketchfab: + return VideoWidgets.Any(w => w.gameObject.activeSelf); + default: + return NonExportableModelWidgets.Any(w => w.gameObject.activeSelf) || + ImageWidgets.Any(w => w.gameObject.activeSelf) || + VideoWidgets.Any(w => w.gameObject.activeSelf); + } + } + + public bool StencilsDisabled + { + get { return m_StencilsDisabled; } + set + { + if (value != m_StencilsDisabled) + { + // Flip flag and visuals for all stencils. + for (int i = 0; i < m_StencilWidgets.Count; ++i) + { + StencilWidget sw = m_StencilWidgets[i].WidgetScript; + if (sw) + { + sw.RefreshVisibility(value); + } + } + m_ActiveStencil = null; + } + m_StencilsDisabled = value; + RefreshPinAndUnpinLists(); + } + } + + private static string CanonicalizeForCompare(string path) + { + return path.ToLower().Replace("\\", "/"); + } + + // Shortens full file paths to "Media Library/[Models | Images]/thing" + // Input: absolute path + // Returns: path starting from Media Library/ (e.g. "Media Library/[Models | Images]/thing") + // or null if path does not lead to Media Library + // Throws: ArgumentException if path is not full + public static string GetPathRootedAtMedia(string path) + { + if (!System.IO.Path.IsPathRooted(path)) + { + throw new ArgumentException("Path is not rooted"); + } + var media = App.MediaLibraryPath(); + if (CanonicalizeForCompare(path).StartsWith(CanonicalizeForCompare(media))) + { + return "Media Library" + path.Substring(media.Length); + } + return null; + } + + // Returns path after Media Library/Models for models only + // Input: absolute path + // Returns: path starting after Models/ or null if the path is not to the Models directory + public static string GetModelSubpath(string fullPath) + { + string media = GetPathRootedAtMedia(fullPath); + string modelPath = "Media Library/Models/"; + if (media == null || !media.StartsWith(modelPath)) + { + return null; + } + return media.Substring(modelPath.Length); + } + + // Used only at .tilt-loading time + public void SetDataFromTilt(TiltModels75[] value) + { + m_loadingTiltModels75 = value; + } + + // Used only at .tilt-loading time + public void SetDataFromTilt(TiltImages75[] value) + { + m_loadingTiltImages75 = value; + } + + // Used only at .tilt-loading time + public void SetDataFromTilt(TiltLights[] value) + { + m_loadingTiltLights = value; + } + + public void SetDataFromTilt(CameraPathMetadata[] cameraPaths) + { + for (int i = 0; i < cameraPaths.Length; ++i) + { + CameraPathWidget.CreateFromSaveData(cameraPaths[i]); + } + } + + public void SetDataFromTilt(TiltVideo[] value) + { + m_loadingTiltVideos = value; + } + + public WidgetPinScript GetWidgetPin() + { + GameObject pinObj = Instantiate(m_WidgetPinPrefab); + pinObj.transform.parent = transform; + return pinObj.GetComponent(); + } + + public void DestroyWidgetPin(WidgetPinScript pin) + { + if (pin != null) + { + Destroy(pin.gameObject); + } + } + + // Set the position that widgets can snap to in the current environment + public void SetHomePosition(Vector3 position) + { + m_Home.SetFixedPosition(position); + } + + // Dormant models are still grabbable but visuals/haptics are disabled + public bool WidgetsDormant + { + get { return m_WidgetsDormant; } + set + { + m_WidgetsDormant = value; + Shader.SetGlobalFloat("_WidgetsDormant", value ? 0 : 1); + } + } + + public float WidgetSnapAngle + { + get { return m_WidgetSnapAngle; } + } + + public bool IsOriginHomeWithinSnapRange(Vector3 pos) + { + return m_Home.WithinRange(pos); + } + + public Transform GetHomeXf() + { + return m_Home.transform; + } + + public void SetHomeOwner(Transform owner) + { + m_Home.SetOwner(owner); + m_Home.Reset(); + } + + public void ClearHomeOwner() + { + m_Home.SetOwner(null); + m_Home.gameObject.SetActive(false); + m_HomeHintLine.SetActive(false); + } + + public void EnableHome(bool bEnable) + { + m_Home.gameObject.SetActive(bEnable); + if (!bEnable) + { + m_HomeHintLine.SetActive(false); + } + } + + public void LoadingState(bool bEnter) + { + m_InhibitGrabWhileLoading = bEnter; + } + + public void UpdateHomeHintLine(Vector3 vModelSnapPos) + { + if (!m_Home.WithinRange(vModelSnapPos) && m_Home.WithinHintRange(vModelSnapPos)) + { + // Enable, position, and scale hint line. + m_HomeHintLine.SetActive(true); + Vector3 vHomeToModel = vModelSnapPos - m_Home.transform.position; + m_HomeHintLine.transform.position = m_Home.transform.position + + (vHomeToModel * 0.5f); + m_HomeHintLine.transform.up = vHomeToModel.normalized; + + Vector3 vScale = m_HomeHintLineBaseScale; + vScale.y = vHomeToModel.magnitude * 0.5f; + m_HomeHintLine.transform.localScale = vScale; + + App.Instance.SelectionEffect.RegisterMesh(m_HomeHintLineMeshFilter); + m_Home.RenderHighlight(); + } + else + { + // Disable the line. + m_HomeHintLine.SetActive(false); + } + } + + public bool MagnetizeToStencils(ref Vector3 pos, ref Quaternion rot, IEnumerable stencilsToIgnore = null) + { + // Early out if stencils are disabled. + if (m_StencilsDisabled && !App.UserConfig.Flags.GuideToggleVisiblityOnly) + { + return false; + } + + Vector3 samplePos = pos; + + bool stencilWasUsed = false; + + // If we're painting, we have a different path for magnetization that relies on the + // previous frame. + if (PointerManager.m_Instance.IsLineEnabled()) + { + // If we don't have an active stencil, we're done here. + if (m_ActiveStencil == null) + { + return false; + } + + // Using the 0 index of m_StencilContactInfos as a shortcut. + m_StencilContactInfos[0].widget = m_ActiveStencil; + FindClosestPointOnWidgetSurface(pos, ref m_StencilContactInfos[0]); + + m_ActiveStencil.SetInUse(true); + pos = m_StencilContactInfos[0].pos; + rot = Quaternion.LookRotation(m_StencilContactInfos[0].normal); + stencilWasUsed = true; + } + else + { + StencilWidget prevStencil = m_ActiveStencil; + float fPrevScore = -m_StencilAttachHysteresis; + int iPrevIndex = -1; + m_ActiveStencil = null; + + // Run through the overlap list and find the best stencil to stick to. + int iPrimaryIndex = -1; + float fBestScore = 0; + int sIndex = 0; + + IEnumerable widgetsToCheck = m_StencilWidgets.Select(w => w.WidgetScript); + if (stencilsToIgnore != null) widgetsToCheck = widgetsToCheck.Except(stencilsToIgnore); + foreach (var sw in widgetsToCheck) + { + Debug.Assert(sw != null); + + // Reset tint + sw.SetInUse(false); + + // Does a rough check to see if the stencil might overlap. OverlapSphereNonAlloc is + // shockingly slow, which is why we don't use it. + Collider collider = sw.GrabCollider; + float centerDist = (collider.bounds.center - samplePos).sqrMagnitude; + if (centerDist > + (StencilAttractDist * StencilAttractDist + collider.bounds.extents.sqrMagnitude)) + { + continue; + } + + m_StencilContactInfos[sIndex].widget = sw; + + FindClosestPointOnWidgetSurface(samplePos, ref m_StencilContactInfos[sIndex]); + + // Find out how far we are from this point and save it as a score. + float distToSurfactPoint = (m_StencilContactInfos[sIndex].pos - samplePos).magnitude; + float score = 1.0f - (distToSurfactPoint / StencilAttractDist); + if (score > fBestScore) + { + iPrimaryIndex = sIndex; + fBestScore = score; + m_ActiveStencil = m_StencilContactInfos[sIndex].widget; + } + + if (m_StencilContactInfos[sIndex].widget == prevStencil) + { + fPrevScore = score; + iPrevIndex = sIndex; + } + + if (++sIndex == m_StencilBucketSize) + { + break; + } + } + + // If we are switching between stencils, check to see if we're switching "enough". + if (iPrevIndex != -1 && m_ActiveStencil != null && prevStencil != m_ActiveStencil) + { + if (fPrevScore + m_StencilAttachHysteresis > fBestScore) + { + m_ActiveStencil = prevStencil; + iPrimaryIndex = iPrevIndex; + } + } + + // If we found a good stencil, return the surface collision transform. + if (m_ActiveStencil != null) + { + m_ActiveStencil.SetInUse(true); + pos = m_StencilContactInfos[iPrimaryIndex].pos; + var up = rot * Vector3.up; + rot = Quaternion.LookRotation(m_StencilContactInfos[iPrimaryIndex].normal, up); + stencilWasUsed = true; + } + + if (prevStencil != m_ActiveStencil) + { + PointerManager.m_Instance.DisablePointerPreviewLine(); + } + } + + return stencilWasUsed; + } + + bool FindClosestPointOnCollider( + Ray rRay, Collider collider, out RaycastHit rHitInfo, float fDist) + { + rHitInfo = new RaycastHit(); + return collider.Raycast(rRay, out rHitInfo, fDist); + } + + void FindClosestPointOnWidgetSurface(Vector3 pos, ref StencilContactInfo info) + { + info.widget.FindClosestPointOnSurface(pos, out info.pos, out info.normal); + } + + public bool ShouldUpdateCollisions() + { + return ActiveGrabWidgets.Any(elt => elt.m_WidgetScript.IsCollisionEnabled()); + } + + public IEnumerable ModelWidgets + { + get + { + return m_ModelWidgets + .Select(w => w == null ? null : w.WidgetScript) + .Where(w => w != null); + } + } + + public IEnumerable LightWidgets + { + get + { + return m_LightWidgets + .Select(w => w == null ? null : w.WidgetScript) + .Where(w => w != null); + } + } + + public IEnumerable VideoWidgets + { + get + { + return m_VideoWidgets + .Select(w => w == null ? null : w.WidgetScript) + .Where(w => w != null); + } + } + + public IEnumerable NonExportableModelWidgets + { + get + { + return m_ModelWidgets + .Select(w => w == null ? null : w.WidgetScript) + .Where(w => w != null).Where(w => !w.Model.AllowExport); + } + } + + public IEnumerable ExportableModelWidgets + { + get + { + return m_ModelWidgets + .Select(w => w == null ? null : w.WidgetScript) + .Where(w => w != null).Where(w => w.Model.AllowExport); + } + } + + public IEnumerable StencilWidgets + { + get + { + return m_StencilWidgets + .Select(d => d == null ? null : d.WidgetScript) + .Where(w => w != null); + } + } + + public StencilWidget GetStencilPrefab(StencilType type) + { + for (int i = 0; i < m_StencilMap.Length; ++i) + { + if (m_StencilMap[i].m_Type == type) + { + return m_StencilMap[i].m_StencilPrefab; + } + } + throw new ArgumentException(type.ToString()); + } + + public IEnumerable ImageWidgets + { + get + { + return m_ImageWidgets + .Select(d => d == null ? null : d.m_WidgetScript as ImageWidget) + .Where(w => w != null); + } + } + + public List GetAllUnselectedActiveWidgets() + { + List widgets = new List(); + GetUnselectedActiveWidgetsInList(m_ModelWidgets); + GetUnselectedActiveWidgetsInList(m_LightWidgets); + GetUnselectedActiveWidgetsInList(m_ImageWidgets); + GetUnselectedActiveWidgetsInList(m_VideoWidgets); + if (!m_StencilsDisabled) + { + GetUnselectedActiveWidgetsInList(m_StencilWidgets); + } + return widgets; + + void GetUnselectedActiveWidgetsInList(List> list) where T : GrabWidget + { + for (int i = 0; i < list.Count; ++i) + { + GrabWidget w = list[i].m_WidgetScript; + if (!w.Pinned && w.transform.parent == App.Scene.ActiveCanvas.transform && + w.gameObject.activeSelf) + { + widgets.Add(w); + } + } + } + } + + public void RefreshPinAndUnpinLists() + { + if (RefreshPinAndUnpinAction != null) + { + m_CanBePinnedWidgets.Clear(); + m_CanBeUnpinnedWidgets.Clear(); + + RefreshPinUnpinWidgetList(m_ModelWidgets); + RefreshPinUnpinWidgetList(m_LightWidgets); + RefreshPinUnpinWidgetList(m_ImageWidgets); + RefreshPinUnpinWidgetList(m_VideoWidgets); + RefreshPinUnpinWidgetList(m_StencilWidgets); + + RefreshPinAndUnpinAction(); + } + + // New in C# 7 - local functions! + void RefreshPinUnpinWidgetList(List> widgetList) where T : GrabWidget + { + foreach (var widgetData in widgetList) + { + var widget = widgetData.WidgetScript; + if (widget.gameObject.activeSelf && widget.AllowPinning) + { + if (widget.Pinned) + { + m_CanBeUnpinnedWidgets.Add(widget); + } + else + { + m_CanBePinnedWidgets.Add(widget); + } + } + } + } + } + + public void RegisterHighlightsForPinnableWidgets(bool pinnable) + { + List widgets = pinnable ? m_CanBePinnedWidgets : m_CanBeUnpinnedWidgets; + for (int i = 0; i < widgets.Count; ++i) + { + GrabWidget w = widgets[i]; + // If stencils are disabled, don't highlight them, cause we can interact with 'em. + if (WidgetManager.m_Instance.StencilsDisabled) + { + if (w is StencilWidget) + { + continue; + } + } + w.RegisterHighlight(); + } + } + + public void RegisterGrabWidget(GameObject rWidget) + { + // Find b/29514616 + if (ReferenceEquals(rWidget, null)) + { + throw new ArgumentNullException("rWidget"); + } + else if (rWidget == null) + { + throw new ArgumentNullException("rWidget(2)"); + } + GrabWidget generic = rWidget.GetComponent(); + if (generic == null) + { + throw new InvalidOperationException($"Object {rWidget.name} is not a GrabWidget"); + } + + if (generic is ModelWidget mw) + { + m_ModelWidgets.Add(new TypedWidgetData(mw)); + } + else if (generic is LightWidget light) + { + m_LightWidgets.Add(new TypedWidgetData(light)); + } + else if (generic is StencilWidget stencil) + { + m_StencilWidgets.Add(new TypedWidgetData(stencil)); + } + else if (generic is ImageWidget image) + { + m_ImageWidgets.Add(new TypedWidgetData(image)); + } + else if (generic is VideoWidget video) + { + m_VideoWidgets.Add(new TypedWidgetData(video)); + } + else if (generic is CameraPathWidget cpw) + { + m_CameraPathWidgets.Add(new TypedWidgetData(cpw)); + } + else + { + m_GrabWidgets.Add(new GrabWidgetData(generic)); + } + + RefreshPinAndUnpinLists(); + } + + // Returns true if a widget was removed + static bool RemoveFrom(List list, GameObject rWidget) + where T : GrabWidgetData + { + int idx = list.FindIndex((data) => data.m_WidgetObject == rWidget); + if (idx != -1) + { + list.RemoveAt(idx); + return true; + } + return false; + } + + public void UnregisterGrabWidget(GameObject rWidget) + { + // Get this widget's batchId out of the map. + sm_BatchMap.Remove(rWidget.GetComponent().BatchId); + + // Pull out of pin tool lists. + RefreshPinAndUnpinLists(); + + // Decrement model vert count if we're a model widget. + ModelWidget mw = rWidget.GetComponent() as ModelWidget; + if (mw != null) + { + m_ModelVertCount -= mw.NumVertsTrackedByWidgetManager; + } + // Same with image widget. + ImageWidget iw = rWidget.GetComponent() as ImageWidget; + if (iw != null) + { + m_ImageVertCount -= iw.NumVertsTrackedByWidgetManager; + } + + if (RemoveFrom(m_ModelWidgets, rWidget)) { return; } + if (RemoveFrom(m_LightWidgets, rWidget)) { return; } + if (RemoveFrom(m_StencilWidgets, rWidget)) { return; } + if (RemoveFrom(m_ImageWidgets, rWidget)) { return; } + if (RemoveFrom(m_VideoWidgets, rWidget)) { return; } + if (RemoveFrom(m_CameraPathWidgets, rWidget)) { return; } + RemoveFrom(m_GrabWidgets, rWidget); + } + + public ImageWidget GetNearestImage(Vector3 pos, float maxDepth, ref Vector3 sampleLoc) + { + ImageWidget bestImage = null; + float leastDistance = float.MaxValue; + foreach (var im in ImageWidgets.Where(i => i.gameObject.activeSelf)) + { + Vector3 dropper_QS; + Vector3 dropper_GS = pos; + Matrix4x4 xfQuadFromGlobal = im.m_ImageQuad.transform.worldToLocalMatrix; + dropper_QS = xfQuadFromGlobal.MultiplyPoint3x4(dropper_GS); + if (Mathf.Abs(dropper_QS.z) < leastDistance + && Mathf.Abs(dropper_QS.x) <= 0.5f + && Mathf.Abs(dropper_QS.y) <= 0.5f + && Mathf.Abs(dropper_QS.z) <= maxDepth / Mathf.Abs(im.GetSignedWidgetSize())) + { + bestImage = im; + leastDistance = Mathf.Abs(dropper_QS.z); + sampleLoc = dropper_QS; + } + } + return bestImage; + } + + public void RefreshNearestWidgetLists(Ray currentGazeRay, int currentGazeObject) + { + m_WidgetsNearBrush.Clear(); + UpdateNearestGrabsFor(InputManager.ControllerName.Brush, currentGazeRay, currentGazeObject); + foreach (GrabWidgetData widget in ActiveGrabWidgets) + { + if (widget.m_NearController) + { + // Deep copy. + m_WidgetsNearBrush.Add(widget.Clone()); + } + } + + m_WidgetsNearWand.Clear(); + UpdateNearestGrabsFor(InputManager.ControllerName.Wand, currentGazeRay, currentGazeObject); + foreach (GrabWidgetData widget in ActiveGrabWidgets) + { + if (widget.m_NearController) + { + m_WidgetsNearWand.Add(widget.Clone()); + } + } + } + + // Helper for RefreshNearestWidgetLists + void UpdateNearestGrabsFor( + InputManager.ControllerName name, Ray currentGazeRay, int currentGazeObject) + { + // Reset hit flags. + foreach (var elt in ActiveGrabWidgets) + { + elt.m_NearController = false; + elt.m_ControllerScore = -1.0f; + } + + Vector3 controllerPos = Vector3.zero; + if (name == InputManager.ControllerName.Brush) + { + controllerPos = InputManager.m_Instance.GetBrushControllerAttachPoint().position; + } + else if (name == InputManager.ControllerName.Wand) + { + controllerPos = InputManager.m_Instance.GetWandControllerAttachPoint().position; + } + else + { + Debug.LogError("UpdateNearestGrabsFor() only supports Brush and Wand controller types."); + } + + // Figure out if controller is in view frustum. If it isn't, don't allow widget grabs. + Vector3 vToController = controllerPos - currentGazeRay.origin; + vToController.Normalize(); + if (Vector3.Angle(vToController, currentGazeRay.direction) > m_GazeMaxAngleFromFacing) + { + return; + } + + BasePanel gazePanel = null; + if (currentGazeObject > -1) + { + gazePanel = PanelManager.m_Instance.GetPanel(currentGazeObject); + } + + foreach (var data in ActiveGrabWidgets) + { + if (!data.m_WidgetScript.enabled) + { + continue; + } + if (m_StencilsDisabled && data.m_WidgetScript is StencilWidget) + { + continue; + } + if (SelectionManager.m_Instance.ShouldRemoveFromSelection() && + !data.m_WidgetScript.CanGrabDuringDeselection()) + { + continue; + } + if (SelectionManager.m_Instance.IsWidgetSelected(data.m_WidgetScript)) + { + continue; + } + float score = data.m_WidgetScript.GetActivationScore(controllerPos, name); + if (score < m_PanelFocusActivationScore && name == InputManager.ControllerName.Brush && + gazePanel && data.m_WidgetObject == gazePanel.gameObject) + { + // If the brush is pointing at a panel, make sure that the panel will be the widget grabbed + score = m_PanelFocusActivationScore; + } + if (score < 0) + { + continue; + } + + data.m_NearController = true; + data.m_ControllerScore = score; + } + } + + public float DistanceToNearestWidget(Ray ray) + { + // If we're in controller mode, find the nearest colliding widget that might get in our way. + float fNearestWidget = 99999.0f; + foreach (var elt in ActiveGrabWidgets) + { + float fWidgetDist = 0.0f; + if (elt.m_WidgetScript.DistanceToCollider(ray, out fWidgetDist)) + { + fNearestWidget = Mathf.Min(fNearestWidget, fWidgetDist); + } + } + return fNearestWidget; + } + + public void DestroyAllWidgets() + { + DestroyWidgetList(m_ModelWidgets); + DestroyWidgetList(m_LightWidgets); + DestroyWidgetList(m_ImageWidgets); + DestroyWidgetList(m_VideoWidgets); + DestroyWidgetList(m_StencilWidgets); + DestroyWidgetList(m_CameraPathWidgets, false); + SetCurrentCameraPath_Internal(null); + App.Switchboard.TriggerAllWidgetsDestroyed(); + + void DestroyWidgetList(List> widgetList, + bool hideBeforeDestroy = true) where T : GrabWidget + { + while (widgetList.Count > 0) + { + GrabWidget widget = widgetList[0].m_WidgetScript; + GameObject obj = widgetList[0].m_WidgetObject; + if (hideBeforeDestroy) { widget.Hide(); } + widget.OnPreDestroy(); + UnregisterGrabWidget(obj); + Destroy(obj); + } + } + } + + /// Upon return: + /// - ImageWidgets have at least an icon-sized Texture2D; it will be mutated with + /// the fullres texture data some time later. + /// - ModelWidgets may have a dummy, invisible Model instead of the actual Model they want; + /// the Model will be automatically replaced with the loaded Model some time later. + public IEnumerator CreateMediaWidgetsFromLoadDataCoroutine() + { + if (m_loadingTiltModels75 != null) + { + OverlayManager.m_Instance.RefuseProgressBarChanges(true); + + if (App.Config.kModelWidgetsWaitForLoad) + { + var assetIds = m_loadingTiltModels75 + .Select(tm => tm.AssetId).Where(aid => aid != null).ToArray(); + // Kick off a bunch of loads... + foreach (var assetId in assetIds) + { + if (App.IcosaAssetCatalog.GetAssetLoadState(assetId) + != IcosaAssetCatalog.AssetLoadState.Loaded) + { + App.IcosaAssetCatalog.RequestModelLoad(assetId, "tiltload"); + } + } + // ... and wait for them to complete + // No widgets have been created yet, so we can't use AreMediaWidgetsStillLoading. + bool IsLoading(string assetId) + { + var state = App.IcosaAssetCatalog.GetAssetLoadState(assetId); + return (state == IcosaAssetCatalog.AssetLoadState.Downloading || + state == IcosaAssetCatalog.AssetLoadState.Loading); + } + while (assetIds.Any(IsLoading)) + { + yield return null; + } + } + + for (int i = 0; i < m_loadingTiltModels75.Length; i++) + { + ModelWidget.CreateFromSaveData(m_loadingTiltModels75[i]); + OverlayManager.m_Instance.UpdateProgress( + (float)(i + 1) / m_loadingTiltModels75.Length, true); + } + OverlayManager.m_Instance.RefuseProgressBarChanges(false); + m_loadingTiltModels75 = null; + } + ModelCatalog.m_Instance.PrintMissingModelWarnings(); + if (m_loadingTiltLights != null) + { + foreach (var light in m_loadingTiltLights) + { + LightWidget.FromTiltLight(light); + } + m_loadingTiltLights = null; + } + if (m_loadingTiltImages75 != null) + { + foreach (TiltImages75 import in m_loadingTiltImages75) + { + // TODO: FromTiltImage should take advantage of being called by a coroutine + // so it can avoid calling ReferenceImage.SynchronousLoad() + ImageWidget.FromTiltImage(import); + } + m_loadingTiltImages75 = null; + } + if (m_loadingTiltVideos != null) + { + foreach (var video in m_loadingTiltVideos) + { + VideoWidget.FromTiltVideo(video); + } + m_loadingTiltVideos = null; + } + yield break; + } + + /// Returns true when all media widgets have finished getting created. + /// Note that: + /// - ImageWidgets may have low-res textures + /// - ModelWidgets may not have a model yet (depending on Config.kModelWidgetsWaitForLoad) + public bool CreatingMediaWidgets => + m_loadingTiltModels75 != null || + m_loadingTiltImages75 != null || + m_loadingTiltVideos != null; + + /// Returns true if any widgets are still waiting for their data. + public bool AreMediaWidgetsStillLoading() + { + if (CreatingMediaWidgets) { return true; } + // Widgets have been created, but some may not have their data yet + IcosaAssetCatalog pac = App.IcosaAssetCatalog; + foreach (var gwd in m_ModelWidgets) + { + Model.Location loc = gwd.WidgetScript.Model.GetLocation(); + if (loc.GetLocationType() == Model.Location.Type.IcosaAssetId) + { + switch (pac.GetAssetLoadState(loc.AssetId)) + { + case IcosaAssetCatalog.AssetLoadState.Downloading: + case IcosaAssetCatalog.AssetLoadState.Loading: + return true; + } + } + } + return false; + } + + // Smaller is better. Invalid objects get negative values. + static float ScoreByAngleAndDistance(GrabWidgetData data) + { + if (!data.m_WidgetScript.Showing) { return -1; } + Transform source = ViewpointScript.Head; + Transform dest = data.m_WidgetObject.transform; + Vector3 delta = (dest.position - source.position); + float dist = delta.magnitude; + return dist / Vector3.Dot(delta.normalized, source.forward); + } + + // Simulate a grab and toss. Use for debugging in monoscopic only. + public void TossNearestWidget() + { + var widget = MediaWidgets.Where(w => w.m_WidgetScript.Showing) + .Select(w => new { score = ScoreByAngleAndDistance(w), widget = w.m_WidgetScript }) + .Where(data => data.score > 0) + .OrderBy(data => data.score) + .FirstOrDefault().widget; + + if (widget != null) + { + if (widget.Pinned) + { + SketchMemoryScript.m_Instance.PerformAndRecordCommand(new PinWidgetCommand(widget, false)); + } + // All media widgets record their movements. + SketchMemoryScript.m_Instance.PerformAndRecordCommand( + new MoveWidgetCommand(widget, widget.LocalTransform, widget.CustomDimension)); + float speed = (App.METERS_TO_UNITS * SketchControlsScript.m_Instance.m_TossThresholdMeters); + Vector3 vLinVel = ViewpointScript.Head.forward * speed; + Vector3 vAngVel = Quaternion.AngleAxis(UnityEngine.Random.Range(0, 360), Vector3.forward) + * ViewpointScript.Head.up * 500; + widget.SetVelocities(vLinVel, vAngVel, widget.transform.position); + } + else + { + Debug.Log("No media in sketch"); + } + } + + public List> ActiveImageWidgets => + m_ImageWidgets.Where(w => w.WidgetScript.gameObject.activeSelf).ToList(); + public List> ActiveLightWidgets => + m_LightWidgets.Where(w => w.WidgetScript.gameObject.activeSelf).ToList(); + public List> ActiveModelWidgets => + m_ModelWidgets.Where(w => w.WidgetScript.gameObject.activeSelf).ToList(); + public List> ActiveVideoWidgets => + m_VideoWidgets.Where(w => w.WidgetScript.gameObject.activeSelf).ToList(); + public List> ActiveCameraPathWidgets => + m_CameraPathWidgets.Where(w => w.WidgetScript.gameObject.activeSelf).ToList(); + + } +} diff --git a/Assets/Scripts/Widgets/DropCamWidget.cs b/Assets/Scripts/Widgets/DropCamWidget.cs index 6e0e799240..cb40b37209 100644 --- a/Assets/Scripts/Widgets/DropCamWidget.cs +++ b/Assets/Scripts/Widgets/DropCamWidget.cs @@ -31,10 +31,11 @@ public class DropCamWidget : GrabWidget { public enum Mode { - SlowFollow, - Stationary, - Wobble, - Circular + SlowFollow = 0, + Stationary = 1, + Wobble = 2, + Circular = 3, + CameraPath = 5600 } public const Mode kDefaultMode = Mode.Stationary; @@ -167,6 +168,7 @@ static public string GetModeName(Mode mode) case Mode.Stationary: return "Stationary"; case Mode.Wobble: return "Figure 8"; case Mode.Circular: return "Circular"; + case Mode.CameraPath: return "Camera Path"; } return ""; } @@ -327,10 +329,48 @@ override protected void OnUpdate() m_GuideCircleObject.SetActive(false); } break; + case Mode.CameraPath: + if (m_UserInteracting) + { + ResetCam(); + } + else + { + m_AnimatedPathTime += Time.deltaTime * (m_CircleSpeed * 20); + FollowCameraPath(); + } + break; } } } + private void FollowCameraPath() + { + var currentPathWidget = WidgetManager.m_Instance.GetCurrentCameraPath().WidgetScript; // TODO Cache + var pathT = new PathT(m_AnimatedPathTime); + pathT.Clamp(currentPathWidget.Path.PositionKnots.Count); + + if (currentPathWidget != null && currentPathWidget.Path.NumPositionKnots > 1) + { + float speed = Mathf.Max(currentPathWidget.Path.GetSpeed(pathT), + CameraPathSpeedKnot.kMinSpeed); + bool completed = currentPathWidget.Path.MoveAlongPath(speed * Time.deltaTime, + pathT, out pathT); + if (completed) + { + // TODO optional looping? + m_AnimatedPathTime = 0; + } + + PathT t = pathT; + float fov = currentPathWidget.Path.GetFov(t); + var cam = GetComponentInChildren(); // TODO Cache + cam.fieldOfView = fov; + transform.position = currentPathWidget.Path.GetPosition(t) - cam.transform.localPosition; + transform.rotation = currentPathWidget.Path.GetRotation(t) * cam.transform.localRotation.Negated(); + } + } + override public void Activate(bool bActive) { base.Activate(bActive); diff --git a/Assets/Scripts/Widgets/ModelWidget.cs b/Assets/Scripts/Widgets/ModelWidget.cs index d26af7f43c..b44b9cf956 100644 --- a/Assets/Scripts/Widgets/ModelWidget.cs +++ b/Assets/Scripts/Widgets/ModelWidget.cs @@ -1,842 +1,879 @@ -// Copyright 2020 The Tilt Brush Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// 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 System.Linq; -using System.Threading.Tasks; - -namespace TiltBrush -{ - - public class ModelWidget : MediaWidget - { - // Do not change otherwise will break backward compatibility with 7.5 save format. - private const float kInitialSizeMeters_RS = 0.25f; - - [SerializeField] private float m_MinContainerRatio; // [0, 1] - [SerializeField] private float m_MaxBloat; - - private Model m_Model; - private string m_Subtree; - public string Subtree - { - get => m_Subtree; - set => m_Subtree = value; - } - - public event Action ScaleChanged; - - private Transform m_ModelInstance; - private ObjModelScript m_ObjModelScript; - private float m_InitSize_CS; - private float m_HideSize_CS; - private bool m_PolyCallbackActive; - - private int m_NumVertsTrackedByWidgetManager; - - /// Returns null if there's no model. - /// Note that it's an error to ask for a model's AssetId unless location type is PolyAssetId. - public string AssetId => m_Model?.AssetId; - - // Returns all leaf meshes which are part of the model, not including those created for auxillary - // purposes, such as ghosting or snapping. - // Analagous to Model.GetMeshes(). - // Do not mutate the return value. - public MeshFilter[] GetMeshes() - { - return m_ObjModelScript.m_MeshChildren; - } - - public Model Model - { - get { return m_Model; } - set - { - // Reduce usage count on old model. - if (m_Model != null) - { - m_Model.m_UsageCount--; - } - m_Model = value; - // Increment usage count on new model. - if (m_Model != null) - { - m_Model.m_UsageCount++; - } - LoadModel(); - } - } - - protected override Vector3 HomeSnapOffset - { - get - { - Vector3 box = m_BoxCollider.size - m_ContainerBloat * App.Scene.Pose.scale; - return m_Size * box * 0.5f * App.Scene.Pose.scale; - } - } - - protected override Vector3 GetHomeSnapLocation(Quaternion snapOrient) - { - return base.GetHomeSnapLocation(snapOrient) - - snapOrient * (App.Scene.Pose.scale * m_Size * m_Model.m_MeshBounds.center); - } - - public override float MaxAxisScale - { - get - { - return Mathf.Max(transform.localScale.x * m_BoxCollider.size.x, - Mathf.Max(transform.localScale.y * m_BoxCollider.size.y, - transform.localScale.z * m_BoxCollider.size.z)); - } - } - - public Bounds WorldSpaceBounds - { - get { return m_BoxCollider.bounds; } - } - - public int NumVertsTrackedByWidgetManager - { - get { return m_NumVertsTrackedByWidgetManager; } - } - - override public int GetTiltMeterCost() - { - return (m_ObjModelScript != null) ? m_ObjModelScript.NumMeshes : 0; - } - - public int GetNumVertsInModel() - { - return (m_ObjModelScript != null) ? m_ObjModelScript.GetNumVertsInMeshes() : 0; - } - - override protected void Awake() - { - base.Awake(); - transform.parent = App.ActiveCanvas.transform; - transform.localScale = Vector3.one; - - // Custom pin scalar for models. - m_PinScalar = 0.5f; - } - - override public void OnPreDestroy() - { - base.OnPreDestroy(); - - if (m_PolyCallbackActive) - { - App.PolyAssetCatalog.CatalogChanged -= OnPacCatalogChanged; - m_PolyCallbackActive = false; - } - // Set our model to null so its usage count is decremented. - Model = null; - } - public override GrabWidget Clone() - { - return Clone(transform.position, transform.rotation, m_Size); - } - - public override GrabWidget Clone(Vector3 position, Quaternion rotation, float size) - { - ModelWidget clone = Instantiate(WidgetManager.m_Instance.ModelWidgetPrefab); - clone.m_PreviousCanvas = m_PreviousCanvas; - clone.transform.position = position; - clone.transform.rotation = rotation; - clone.Model = Model; - // We're obviously not loading from a sketch. This is to prevent the intro animation. - // TODO: Change variable name to something more explicit of what this flag does. - clone.m_LoadingFromSketch = true; - clone.Show(true, false); - clone.AddSceneLightGizmos(); - clone.transform.parent = transform.parent; - clone.SetSignedWidgetSize(size); - clone.m_Subtree = m_Subtree; - clone.SyncHierarchyToSubtree(); - HierarchyUtils.RecursivelySetLayer(clone.transform, gameObject.layer); - TiltMeterScript.m_Instance.AdjustMeterWithWidget(clone.GetTiltMeterCost(), up: true); - - CanvasScript canvas = transform.parent.GetComponent(); - if (canvas != null) - { - var materials = clone.GetComponentsInChildren().SelectMany(x => x.materials); - foreach (var material in materials) - { - foreach (string keyword in canvas.BatchManager.MaterialKeywords) - { - material.EnableKeyword(keyword); - } - } - } - - if (!clone.Model.m_Valid) - { - App.PolyAssetCatalog.CatalogChanged += clone.OnPacCatalogChanged; - clone.m_PolyCallbackActive = true; - } - clone.CloneInitialMaterials(this); - clone.TrySetCanvasKeywordsFromObject(transform); - return clone; - } - - protected override void OnHideStart() - { - m_HideSize_CS = m_Size; - } - - public void OnPacCatalogChanged() - { - Model model = App.PolyAssetCatalog.GetModel(AssetId); - if (model != null && model.m_Valid) - { - Model = model; - SetSignedWidgetSize(m_Size); - - // TODO: We may not want to do this, eventually. Perhaps we continue to receive messages, - // get our asset each time, and do a diff to see if we should reload it. - App.PolyAssetCatalog.CatalogChanged -= OnPacCatalogChanged; - m_PolyCallbackActive = false; - } - } - - override protected void SetWidgetSizeInternal(float fScale) - { - base.SetWidgetSizeInternal(fScale); - if (Mathf.Abs(fScale - m_Size) > float.Epsilon) - { - ScaleChanged?.Invoke(); - } - } - - public override string GetExportName() - { - return Model.GetExportName(); - } - - void LoadModel() - { - // Clean up existing model - if (m_ModelInstance != null) - { - GameObject.Destroy(m_ModelInstance.gameObject); - } - - // Early out if we don't have a model to clone. - // This can happen if model loading is deferred. - if (m_Model == null || m_Model.m_ModelParent == null) - { - return; - } - - m_ModelInstance = Instantiate(m_Model.m_ModelParent); - m_ModelInstance.gameObject.SetActive(true); - m_ModelInstance.parent = this.transform; - - Coords.AsLocal[m_ModelInstance] = TrTransform.identity; - float maxExtent = 2 * Mathf.Max(m_Model.m_MeshBounds.extents.x, - Mathf.Max(m_Model.m_MeshBounds.extents.y, m_Model.m_MeshBounds.extents.z)); - float size; - if (maxExtent == 0.0f) - { - // If we created a widget with a model that doesn't have geo, we won't have calculated a - // bounds worth much. In that case, give us a default size. - size = 1.0f; - } - else - { - size = kInitialSizeMeters_RS * App.METERS_TO_UNITS / maxExtent; - } - - m_InitSize_CS = size / Coords.CanvasPose.scale; - - // Models are created in the main canvas. Cache model layer in case it's overridden later. - HierarchyUtils.RecursivelySetLayer(transform, App.Scene.MainCanvas.gameObject.layer); - m_BackupLayer = m_ModelInstance.gameObject.layer; - - // Set a new batchId on this model so it can be picked up in GPU intersections. - m_BatchId = GpuIntersector.GetNextBatchId(); - HierarchyUtils.RecursivelySetMaterialBatchID(m_ModelInstance, m_BatchId); - WidgetManager.m_Instance.AddWidgetToBatchMap(this, m_BatchId); - - Vector3 ratios = GetBoundsRatios(m_Model.m_MeshBounds); - m_ContainerBloat.x = Mathf.Max(0, m_MinContainerRatio - ratios.x); - m_ContainerBloat.y = Mathf.Max(0, m_MinContainerRatio - ratios.y); - m_ContainerBloat.z = Mathf.Max(0, m_MinContainerRatio - ratios.z); - m_ContainerBloat /= m_MinContainerRatio; // Normalize for the min ratio. - m_ContainerBloat *= m_MaxBloat / App.Scene.Pose.scale; // Apply bloat to appropriate axes. - - m_BoxCollider.size = m_Model.m_MeshBounds.size + m_ContainerBloat; - m_BoxCollider.transform.localPosition = m_Model.m_MeshBounds.center; - - InitSnapGhost(m_Model.m_ModelParent, m_ModelInstance); - - // Remove previous model vertex recording. - WidgetManager.m_Instance.AdjustModelVertCount(-m_NumVertsTrackedByWidgetManager); - m_NumVertsTrackedByWidgetManager = 0; - - m_ObjModelScript = GetComponentInChildren(); - m_ObjModelScript.Init(); - if (m_ObjModelScript.NumMeshes == 0) - { - OutputWindowScript.Error("No usable geometry in model"); - } - else - { - m_NumVertsTrackedByWidgetManager = m_ObjModelScript.GetNumVertsInMeshes(); - WidgetManager.m_Instance.AdjustModelVertCount(m_NumVertsTrackedByWidgetManager); - } - - if (m_Model.IsCached()) - { - m_Model.RefreshCache(); - } - } - - public bool HasSubModels() - { - string ext = Model.GetLocation().Extension; - if (ext == ".gltf" || ext == ".glb") - { - int lightCount = m_ObjModelScript.GetComponentsInChildren().Length; - int meshCount = GetMeshes().Length; - return lightCount + meshCount > 1; - } - else if (m_Model.GetLocation().Extension == ".svg") - { - return m_ObjModelScript.SvgSceneInfo.HasSubShapes(); - } - return false; - } - - public void SyncHierarchyToSubtree(string previousSubtree = null) - { - if (string.IsNullOrEmpty(Subtree)) return; - // Walk the hierarchy and find the matching node - Transform oldRoot = m_ObjModelScript.transform; - Transform node = oldRoot; - - // We only want to walk the new part of the hierarchy - string subpathToTraverse; - if (!string.IsNullOrEmpty(previousSubtree)) - { - subpathToTraverse = m_Subtree.Substring(previousSubtree.Length); - } - else - { - subpathToTraverse = m_Subtree; - } - subpathToTraverse = subpathToTraverse.Trim('/'); - - bool excludeChildren = false; - if (subpathToTraverse.EndsWith(".mesh")) - { - subpathToTraverse = subpathToTraverse.Substring(0, subpathToTraverse.Length - 5); - excludeChildren = true; - } - if (node.name == subpathToTraverse) - { - // We're already at the right node - // No need to do anything - Debug.LogWarning($"Didn't expect to get here..."); - } - else - { - // node will be null if not found - node = node.Find(subpathToTraverse); - } - - if (node != null) - { - if (excludeChildren) - { - foreach (Transform child in node) - { - Destroy(child.gameObject); - } - } - var newRoot = new GameObject(); - newRoot.transform.SetParent(transform); - newRoot.name = $"LocalFile:{m_Model.RelativePath}#{m_Subtree}"; - m_ObjModelScript = newRoot.AddComponent(); - node.SetParent(newRoot.transform, worldPositionStays: true); - - oldRoot.gameObject.SetActive(false); // TODO destroy might fail on first load so also hide - Destroy(oldRoot.gameObject); - - m_ObjModelScript.Init(); - if (excludeChildren) - { - // Destroyed children aren't destroyed immediately, so we need to assign them manually - var mf = node.GetComponent(); - var smr = node.GetComponent(); - m_ObjModelScript.m_MeshChildren = mf != null ? new[] { mf } : Array.Empty(); - m_ObjModelScript.m_SkinnedMeshChildren = smr != null ? new[] { smr } : Array.Empty(); - } - - CloneInitialMaterials(null); - RecalculateColliderBounds(); - } - } - - public void RecalculateColliderBounds() - { - var widgetTransform = m_ObjModelScript.transform.parent; - - // Save the widget's original transform - var oldParent = widgetTransform.parent; - var oldPosition = widgetTransform.localPosition; - var oldRotation = widgetTransform.localRotation; - var oldScale = widgetTransform.localScale; - - // Move it to the origin - widgetTransform.SetParent(null); - widgetTransform.localPosition = Vector3.zero; - widgetTransform.localRotation = Quaternion.identity; - widgetTransform.localScale = Vector3.one; - - // Reset the collider gameobject transform - m_BoxCollider.transform.localPosition = Vector3.zero; - m_BoxCollider.transform.localRotation = Quaternion.identity; - m_BoxCollider.transform.localScale = Vector3.one; - - // Collect the renderers - var meshRenderers = m_ObjModelScript - .m_MeshChildren - .Select(x => x.GetComponent()); - var skinnedMeshRenderers = m_ObjModelScript.m_SkinnedMeshChildren; - - // Calculate the bounds - Bounds b = new Bounds(); - bool first = true; - var boundsList = meshRenderers.Select(x => x.bounds).ToList(); - boundsList.AddRange(skinnedMeshRenderers.Select(x => x.bounds)); - - for (var i = 0; i < boundsList.Count; i++) - { - var bounds = boundsList[i]; - - if (first) - { - b = bounds; - first = false; - } - else - { - b.Encapsulate(bounds); - } - } - - m_MeshBounds = b; - m_BoxCollider.transform.localPosition = m_MeshBounds.center; - m_BoxCollider.size = m_MeshBounds.size; - - // Restore the widget's original transform - widgetTransform.SetParent(oldParent); - widgetTransform.localPosition = oldPosition; - widgetTransform.localRotation = oldRotation; - widgetTransform.localScale = oldScale; - } - - public override float GetActivationScore(Vector3 vControllerPos, InputManager.ControllerName name) - { - Vector3 vInvTransformedPos = m_BoxCollider.transform.InverseTransformPoint(vControllerPos); - Vector3 vSize = m_BoxCollider.size * 0.5f; - float xDiff = vSize.x - Mathf.Abs(vInvTransformedPos.x); - float yDiff = vSize.y - Mathf.Abs(vInvTransformedPos.y); - float zDiff = vSize.z - Mathf.Abs(vInvTransformedPos.z); - if (xDiff > 0.0f && yDiff > 0.0f && zDiff > 0.0f) - { - float minSize = Mathf.Abs(m_Size) * - Mathf.Min(m_BoxCollider.size.x, Mathf.Min(m_BoxCollider.size.y, m_BoxCollider.size.z)); - return (xDiff / vSize.x + yDiff / vSize.y + zDiff / vSize.z) / 3 / (minSize + 1); - } - return -1.0f; - } - - private static Vector3 GetBoundsRatios(Bounds bounds) - { - float maxExtent = 0.001f; // epsilon to avoid division by zero - maxExtent = Mathf.Max(maxExtent, bounds.extents.x); - maxExtent = Mathf.Max(maxExtent, bounds.extents.y); - maxExtent = Mathf.Max(maxExtent, bounds.extents.z); - - return new Vector3( - bounds.extents.x / maxExtent, - bounds.extents.y / maxExtent, - bounds.extents.z / maxExtent); - } - - protected override void OnShow() - { - base.OnShow(); - - if (m_Model != null && m_Model.m_Valid) - { - SetSignedWidgetSize(0.0f); - } - - if (!m_LoadingFromSketch) - { - m_IntroAnimState = IntroAnimState.In; - Debug.Assert(!IsMoving(), "Shouldn't have velocity!"); - ClearVelocities(); - m_IntroAnimValue = 0.0f; - UpdateIntroAnim(); - } - else - { - m_IntroAnimState = IntroAnimState.On; - } - } - - protected override void OnUpdate() - { - // During transitions, scale up and down. - if (m_CurrentState == State.Hiding) - { - SetWidgetSizeAboutCenterOfMass(m_HideSize_CS * GetShowRatio()); - } - } - - protected override void UpdateIntroAnim() - { - base.UpdateIntroAnim(); - if (!m_LoadingFromSketch) - { - SetWidgetSizeAboutCenterOfMass(m_InitSize_CS * m_IntroAnimValue); - } - } - - protected override void UpdateScale() - { - if (this == null) return; // BreakModelApartCommand can destroy us - transform.localScale = Vector3.one * m_Size; - if (m_Model != null && m_Model.m_Valid) - { - m_BoxCollider.size = MeshBounds.size + m_ContainerBloat; - } - } - - private Bounds m_MeshBounds; - public Bounds MeshBounds - { - get - { - if (string.IsNullOrEmpty(m_Subtree)) - { - return m_Model.m_MeshBounds; - } - return m_MeshBounds; - } - } - - override protected void InitPin() - { - base.InitPin(); - // Move the pin closer to the center since the bounds around the mesh might not be very tight. - m_Pin.SetPenetrationScalar(.25f); - } - - public override void RegisterHighlight() - { -#if !(UNITY_ANDROID || UNITY_IOS) - if (m_ObjModelScript != null) - { - m_ObjModelScript.RegisterHighlight(); - return; - } -#endif - base.RegisterHighlight(); - } - - protected override void UnregisterHighlight() - { -#if !(UNITY_ANDROID || UNITY_IOS) - if (m_ObjModelScript != null) - { - m_ObjModelScript.UnregisterHighlight(); - return; - } -#endif - base.UnregisterHighlight(); - } - - public TrTransform GetSaveTransform() - { - var xf = TrTransform.FromLocalTransform(transform); - xf.scale = GetSignedWidgetSize(); - return xf; - } - - public override Vector2 GetWidgetSizeRange() - { - // m_Model can be null in the event we're pulling the model from Poly. - if (m_Model == null || !m_Model.m_Valid) - { - // Don't enforce a size range if we don't know the extents yet. - // It will be contrained when the model loads in and the bounds are known. - return new Vector2(float.MinValue, float.MaxValue); - } - float maxExtent = 2 * Mathf.Max(m_Model.m_MeshBounds.extents.x, - Mathf.Max(m_Model.m_MeshBounds.extents.y, m_Model.m_MeshBounds.extents.z)); - // If we created a widget with a model that doesn't have geo, we won't have calculated a - // bounds with great data. Protect against divide by zero. - if (maxExtent == 0.0f) - { - maxExtent = 1.0f; - } - return new Vector2(m_MinSize_CS / maxExtent, m_MaxSize_CS / maxExtent); - } - - /// This method is for use when loading widgets that use the pre-M13 file format, - /// which is normalized with respect to min and max size (ie: the transform is not "raw") - public void SetWidgetSizeNonRaw(float fScale) - { - Vector3 extents = m_Model.m_MeshBounds.extents; - float maxExtent = Mathf.Max(extents.x, Mathf.Max(extents.y, extents.z)); - // If we created a widget with a model that doesn't have geo, we won't have calculated a - // bounds with great data. Protect against divide by zero. - if (maxExtent == 0.0f) - { - maxExtent = 1.0f; - } - float sizeRatio = kInitialSizeMeters_RS / 2 / maxExtent; - SetSignedWidgetSize(fScale * sizeRatio * 10); - } - - - /// Updates the scale of the object, but with the center-of-scale - /// being the center of mass's origin, as opposed to the widget's origin. - /// Postconditions: - /// - GetWidgetSize() == size - /// - CenterOfMassPose_LS is unchanged (modulo precision issues) - protected void SetWidgetSizeAboutCenterOfMass(float size) - { - if (m_Size == size) { return; } - - // Use WithUnitScale because we want only the pos/rot difference - // Find delta such that delta * new = old - var oldCm_LS = WithUnitScale(CenterOfMassPose_LS); - m_Size = size; - UpdateScale(); - var newCm_LS = WithUnitScale(CenterOfMassPose_LS); - var delta_LS = oldCm_LS * newCm_LS.inverse; - if (CenterOfMassTransform == transform) - { - // Edge case when they are equal: delta_LS will only be approximately identity. - // Make it exactly identity for a smidge more accuracy - delta_LS = TrTransform.identity; - } - - LocalTransform = delta_LS * LocalTransform; - } - - /// I believe (but am not sure) that Media Library content loads synchronously, - /// and PAC content loads asynchronously. - public static async void CreateFromSaveData(TiltModels75 modelDatas) - { - Debug.AssertFormat(modelDatas.AssetId == null || modelDatas.FilePath == null, - "Model Data should not have an AssetID *and* a File Path"); - Debug.AssertFormat(!modelDatas.InSet_deprecated, - "InSet should have been removed at load time"); - - bool ok; - if (modelDatas.FilePath != null) - { - - Task okTask = CreateModelsFromRelativePath( - modelDatas.FilePath, modelDatas.Subtrees, - modelDatas.Transforms, modelDatas.RawTransforms, modelDatas.PinStates, - modelDatas.GroupIds, modelDatas.LayerIds); - ok = await okTask; - - } - else if (modelDatas.AssetId != null) - { - CreateModelsFromAssetId( - modelDatas.AssetId, modelDatas.Subtrees, - modelDatas.RawTransforms, modelDatas.PinStates, modelDatas.GroupIds, modelDatas.LayerIds); - ok = true; - } - else - { - Debug.LogError("Model Data doesn't contain an AssetID or File Path."); - ok = false; - } - - if (!ok) - { - ModelCatalog.m_Instance.AddMissingModel( - modelDatas.FilePath, modelDatas.Transforms, modelDatas.RawTransforms); - } - } - - /// I believe (but am not sure) that this is synchronous. - /// Returns false if the model can't be loaded -- in this case, caller is responsible - /// for creating the missing-model placeholder. - public static async Task CreateModelsFromRelativePath( - string relativePath, string[] subtrees, TrTransform[] xfs, TrTransform[] rawXfs, bool[] pinStates, uint[] groupIds, int[] layerIds) - { - // Verify model is loaded. Or, at least, has been tried to be loaded. - Model model = ModelCatalog.m_Instance.GetModel(relativePath); - if (model == null) { return false; } - - if (!model.m_Valid) - { - // Reload the model if it's not valid or if we're loading a subtree. - Task t = model.LoadModelAsync(); - await t; - } - if (!model.m_Valid) - { - return false; - } - - if (xfs != null) - { - // Pre M13 format - for (int i = 0; i < xfs.Length; ++i) - { - bool pin = (pinStates != null && i < pinStates.Length) ? pinStates[i] : true; - uint groupId = (groupIds != null && i < groupIds.Length) ? groupIds[i] : 0; - CreateModel(model, subtrees[i], xfs[i], pin, isNonRawTransform: true, groupId, 0); - } - } - if (rawXfs != null) - { - // Post M13 format - for (int i = 0; i < rawXfs.Length; ++i) - { - bool pin = (pinStates != null && i < pinStates.Length) ? pinStates[i] : true; - uint groupId = (groupIds != null && i < groupIds.Length) ? groupIds[i] : 0; - int layerId = (layerIds != null && i < layerIds.Length) ? layerIds[i] : 0; - CreateModel(model, subtrees[i], rawXfs[i], pin, isNonRawTransform: false, groupId, layerId); - } - } - return true; - } - - /// isNonRawTransform - true if the transform uses the pre-M13 meaning of transform.scale. - static void CreateModel(Model model, string subtree, TrTransform xf, bool pin, - bool isNonRawTransform, uint groupId, int layerId, string assetId = null) - { - - var modelWidget = Instantiate(WidgetManager.m_Instance.ModelWidgetPrefab) as ModelWidget; - modelWidget.transform.localPosition = xf.translation; - modelWidget.transform.localRotation = xf.rotation; - modelWidget.Model = model; - modelWidget.m_Subtree = subtree; - modelWidget.SyncHierarchyToSubtree(); - modelWidget.m_LoadingFromSketch = true; - modelWidget.Show(true, false); - if (isNonRawTransform) - { - modelWidget.SetWidgetSizeNonRaw(xf.scale); - modelWidget.transform.localPosition -= - xf.rotation * modelWidget.Model.m_MeshBounds.center * modelWidget.GetSignedWidgetSize(); - } - else - { - modelWidget.SetSignedWidgetSize(xf.scale); - } - TiltMeterScript.m_Instance.AdjustMeterWithWidget(modelWidget.GetTiltMeterCost(), up: true); - if (pin) - { - modelWidget.PinFromSave(); - } - - if (assetId != null && !model.m_Valid) - { - App.PolyAssetCatalog.CatalogChanged += modelWidget.OnPacCatalogChanged; - modelWidget.m_PolyCallbackActive = true; - } - modelWidget.Group = App.GroupManager.GetGroupFromId(groupId); - modelWidget.SetCanvas(App.Scene.GetOrCreateLayer(layerId)); - } - - // Used when loading model assetIds from a serialized format (e.g. Tilt file). - static void CreateModelsFromAssetId(string assetId, string[] subtrees, TrTransform[] rawXfs, - bool[] pinStates, uint[] groupIds, int[] layerIds) - { - // Request model from Poly and if it doesn't exist, ask to load it. - Model model = App.PolyAssetCatalog.GetModel(assetId); - if (model == null) - { - // This Model is transient; the Widget will replace it with a good Model from the PAC - // as soon as the PAC loads it. - model = new Model(Model.Location.PolyAsset(assetId, null)); - } - if (!model.m_Valid) - { - App.PolyAssetCatalog.RequestModelLoad(assetId, "widget"); - } - - // Create a widget for each transform. - for (int i = 0; i < rawXfs.Length; ++i) - { - bool pin = (i < pinStates.Length) ? pinStates[i] : true; - uint groupId = (groupIds != null && i < groupIds.Length) ? groupIds[i] : 0; - int layerId = (layerIds != null && i < layerIds.Length) ? layerIds[i] : 0; - CreateModel(model, subtrees[i], rawXfs[i], pin, isNonRawTransform: false, groupId, layerId, assetId); - } - } - - override public bool HasGPUIntersectionObject() - { - return m_ModelInstance != null; - } - - override public void SetGPUIntersectionObjectLayer(int layer) - { - HierarchyUtils.RecursivelySetLayer(m_ModelInstance, layer); - } - - override public void RestoreGPUIntersectionObjectLayer() - { - HierarchyUtils.RecursivelySetLayer(m_ModelInstance, m_BackupLayer); - } - - override public bool CanSnapToHome() - { - return m_Model.m_MeshBounds.center == Vector3.zero; - } - - public void AddSceneLightGizmos() - { - var lights = m_ObjModelScript.transform.GetComponentsInChildren(); - foreach (var light in lights) - { - // Probably not the right place to do it but we have to it somewhere - light.renderMode = LightRenderMode.ForceVertex; - Transform tr = Instantiate( - WidgetManager.m_Instance.SceneLightGizmoPrefab.transform, - light.transform - ); - var gizmo = tr.GetComponent(); - gizmo.SetupLightGizmos(light); - } - } - - public void UpdateBatchInfo() - { - // Set a new batchId on this model so it can be picked up in GPU intersections. - m_BatchId = GpuIntersector.GetNextBatchId(); - HierarchyUtils.RecursivelySetMaterialBatchID(m_ModelInstance, m_BatchId); - WidgetManager.m_Instance.AddWidgetToBatchMap(this, m_BatchId); - } - } -} // namespace TiltBrush +// Copyright 2020 The Tilt Brush Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// 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 UnityEngine; +using System.Linq; +using System.Threading.Tasks; + +namespace TiltBrush +{ + + public class ModelWidget : MediaWidget + { + // Do not change otherwise will break backward compatibility with 7.5 save format. + private const float kInitialSizeMeters_RS = 0.25f; + + [SerializeField] private float m_MinContainerRatio; // [0, 1] + [SerializeField] private float m_MaxBloat; + + private Model m_Model; + + + // What is Subtree? + // e.g. if we have 3d model with 3 chairs with the hierarchy below, + // then when the model is broken apart, we create a separate ModelWidget for each Chair1,Chair2,Chair3 + // e.g for Chair1, Subtree = "Root/Chair1" + /* + Root (empty node) + Chair1 (mesh) + Chair2 (mesh) + Chair3 (mesh) + */ + private string m_Subtree; + public string Subtree + { + get => m_Subtree; + set => m_Subtree = value; + } + + public event Action ScaleChanged; + + private Transform m_ModelInstance; + private ObjModelScript m_ObjModelScript; + private float m_InitSize_CS; + private float m_HideSize_CS; + private bool m_PolyCallbackActive; + + private int m_NumVertsTrackedByWidgetManager; + + /// Returns null if there's no model. + /// Note that it's an error to ask for a model's AssetId unless location type is PolyAssetId. + public string AssetId => m_Model?.AssetId; + + // Returns all leaf meshes which are part of the model, not including those created for auxillary + // purposes, such as ghosting or snapping. + // Analagous to Model.GetMeshes(). + // Do not mutate the return value. + public MeshFilter[] GetMeshes() + { + return m_ObjModelScript.m_MeshChildren; + } + + public Model Model + { + get { return m_Model; } + set + { + // Reduce usage count on old model. + if (m_Model != null) + { + m_Model.m_UsageCount--; + } + m_Model = value; + // Increment usage count on new model. + if (m_Model != null) + { + m_Model.m_UsageCount++; + } + LoadModel(); + } + } + + protected override Vector3 HomeSnapOffset + { + get + { + Vector3 box = m_BoxCollider.size - m_ContainerBloat * App.Scene.Pose.scale; + return m_Size * box * 0.5f * App.Scene.Pose.scale; + } + } + + protected override Vector3 GetHomeSnapLocation(Quaternion snapOrient) + { + return base.GetHomeSnapLocation(snapOrient) - + snapOrient * (App.Scene.Pose.scale * m_Size * m_Model.m_MeshBounds.center); + } + + public override float MaxAxisScale + { + get + { + return Mathf.Max(transform.localScale.x * m_BoxCollider.size.x, + Mathf.Max(transform.localScale.y * m_BoxCollider.size.y, + transform.localScale.z * m_BoxCollider.size.z)); + } + } + + public Bounds WorldSpaceBounds + { + get { return m_BoxCollider.bounds; } + } + + public int NumVertsTrackedByWidgetManager + { + get { return m_NumVertsTrackedByWidgetManager; } + } + + override public int GetTiltMeterCost() + { + return (m_ObjModelScript != null) ? m_ObjModelScript.NumMeshes : 0; + } + + public int GetNumVertsInModel() + { + return (m_ObjModelScript != null) ? m_ObjModelScript.GetNumVertsInMeshes() : 0; + } + + override protected void Awake() + { + base.Awake(); + transform.parent = App.ActiveCanvas.transform; + transform.localScale = Vector3.one; + + // Custom pin scalar for models. + m_PinScalar = 0.5f; + } + + override public void OnPreDestroy() + { + base.OnPreDestroy(); + + if (m_PolyCallbackActive) + { + App.IcosaAssetCatalog.CatalogChanged -= OnPacCatalogChanged; + m_PolyCallbackActive = false; + } + // Set our model to null so its usage count is decremented. + Model = null; + } + public override GrabWidget Clone() + { + return Clone(transform.position, transform.rotation, m_Size); + } + + public override GrabWidget Clone(Vector3 position, Quaternion rotation, float size) + { + ModelWidget clone = Instantiate(WidgetManager.m_Instance.ModelWidgetPrefab); + clone.m_PreviousCanvas = m_PreviousCanvas; + clone.transform.position = position; + clone.transform.rotation = rotation; + clone.Model = Model; + // We're obviously not loading from a sketch. This is to prevent the intro animation. + // TODO: Change variable name to something more explicit of what this flag does. + clone.m_LoadingFromSketch = true; + clone.Show(true, false); + clone.AddSceneLightGizmos(); + clone.transform.parent = transform.parent; + clone.SetSignedWidgetSize(size); + clone.m_Subtree = m_Subtree; + clone.SyncHierarchyToSubtree(); + HierarchyUtils.RecursivelySetLayer(clone.transform, gameObject.layer); + TiltMeterScript.m_Instance.AdjustMeterWithWidget(clone.GetTiltMeterCost(), up: true); + + CanvasScript canvas = transform.parent.GetComponent(); + if (canvas != null) + { + var materials = clone.GetComponentsInChildren().SelectMany(x => x.materials); + foreach (var material in materials) + { + foreach (string keyword in canvas.BatchManager.MaterialKeywords) + { + material.EnableKeyword(keyword); + } + } + } + + if (!clone.Model.m_Valid) + { + App.IcosaAssetCatalog.CatalogChanged += clone.OnPacCatalogChanged; + clone.m_PolyCallbackActive = true; + } + clone.CloneInitialMaterials(this); + clone.TrySetCanvasKeywordsFromObject(transform); + return clone; + } + + protected override void OnHideStart() + { + m_HideSize_CS = m_Size; + } + + public void OnPacCatalogChanged() + { + Model model = App.IcosaAssetCatalog.GetModel(AssetId); + if (model != null && model.m_Valid) + { + Model = model; + SetSignedWidgetSize(m_Size); + + // TODO: We may not want to do this, eventually. Perhaps we continue to receive messages, + // get our asset each time, and do a diff to see if we should reload it. + App.IcosaAssetCatalog.CatalogChanged -= OnPacCatalogChanged; + m_PolyCallbackActive = false; + } + } + + override protected void SetWidgetSizeInternal(float fScale) + { + base.SetWidgetSizeInternal(fScale); + if (Mathf.Abs(fScale - m_Size) > float.Epsilon) + { + ScaleChanged?.Invoke(); + } + } + + public override string GetExportName() + { + return Model.GetExportName(); + } + + void LoadModel() + { + // Clean up existing model + if (m_ModelInstance != null) + { + GameObject.Destroy(m_ModelInstance.gameObject); + } + + // Early out if we don't have a model to clone. + // This can happen if model loading is deferred. + if (m_Model == null || m_Model.m_ModelParent == null) + { + return; + } + + m_ModelInstance = Instantiate(m_Model.m_ModelParent); + m_ModelInstance.gameObject.SetActive(true); + m_ModelInstance.parent = this.transform; + + Coords.AsLocal[m_ModelInstance] = TrTransform.identity; + float maxExtent = 2 * Mathf.Max(m_Model.m_MeshBounds.extents.x, + Mathf.Max(m_Model.m_MeshBounds.extents.y, m_Model.m_MeshBounds.extents.z)); + float size; + if (maxExtent == 0.0f) + { + // If we created a widget with a model that doesn't have geo, we won't have calculated a + // bounds worth much. In that case, give us a default size. + size = 1.0f; + } + else + { + size = kInitialSizeMeters_RS * App.METERS_TO_UNITS / maxExtent; + } + + m_InitSize_CS = size / Coords.CanvasPose.scale; + + // Models are created in the main canvas. Cache model layer in case it's overridden later. + HierarchyUtils.RecursivelySetLayer(transform, App.Scene.MainCanvas.gameObject.layer); + m_BackupLayer = m_ModelInstance.gameObject.layer; + + // Set a new batchId on this model so it can be picked up in GPU intersections. + m_BatchId = GpuIntersector.GetNextBatchId(); + HierarchyUtils.RecursivelySetMaterialBatchID(m_ModelInstance, m_BatchId); + WidgetManager.m_Instance.AddWidgetToBatchMap(this, m_BatchId); + + Vector3 ratios = GetBoundsRatios(m_Model.m_MeshBounds); + m_ContainerBloat.x = Mathf.Max(0, m_MinContainerRatio - ratios.x); + m_ContainerBloat.y = Mathf.Max(0, m_MinContainerRatio - ratios.y); + m_ContainerBloat.z = Mathf.Max(0, m_MinContainerRatio - ratios.z); + m_ContainerBloat /= m_MinContainerRatio; // Normalize for the min ratio. + m_ContainerBloat *= m_MaxBloat / App.Scene.Pose.scale; // Apply bloat to appropriate axes. + + m_BoxCollider.size = m_Model.m_MeshBounds.size + m_ContainerBloat; + m_BoxCollider.transform.localPosition = m_Model.m_MeshBounds.center; + + InitSnapGhost(m_Model.m_ModelParent, m_ModelInstance); + + // Remove previous model vertex recording. + WidgetManager.m_Instance.AdjustModelVertCount(-m_NumVertsTrackedByWidgetManager); + m_NumVertsTrackedByWidgetManager = 0; + + m_ObjModelScript = GetComponentInChildren(); + m_ObjModelScript.Init(); + if (m_ObjModelScript.NumMeshes == 0) + { + OutputWindowScript.Error("No usable geometry in model"); + } + else + { + m_NumVertsTrackedByWidgetManager = m_ObjModelScript.GetNumVertsInMeshes(); + WidgetManager.m_Instance.AdjustModelVertCount(m_NumVertsTrackedByWidgetManager); + } + + if (m_Model.IsCached()) + { + m_Model.RefreshCache(); + } + } + + public bool HasSubModels() + { + string ext = Model.GetLocation().Extension; + if (ext == ".gltf" || ext == ".gltf2" || ext == ".glb") + { + int lightCount = m_ObjModelScript.GetComponentsInChildren().Length; + int meshCount = GetMeshes().Length; + return lightCount + meshCount > 1; + } + else if (m_Model.GetLocation().Extension == ".svg") + { + return m_ObjModelScript.SvgSceneInfo.HasSubShapes(); + } + return false; + } + + // Update the transform hierarchy of this ModelWidget to only contain m_Subtree + // e.g if Subtree = "CarBody/Floor/Wheel1", then this method will update the transform hierarchy to contain nodes + // starting at CarBody/Floor/Wheel1 + public void SyncHierarchyToSubtree(string previousSubtree = null) + { + if (string.IsNullOrEmpty(Subtree)) return; + // Walk the hierarchy and find the matching node + Transform oldRoot = m_ObjModelScript.transform; + Transform node = oldRoot; + + // We only want to walk the new part of the hierarchy + string subpathToTraverse; + if (!string.IsNullOrEmpty(previousSubtree)) + { + + // example case: + // previousSubtree = CarBody/Floor + // m_Subtree = CarBody/Floor/Wheel1 + // subpathToTraverse should be Floor/Wheel1 + + // Floor + string lastLevel = previousSubtree.Split("/")[^1]; + + int startIndex = previousSubtree.Length - (lastLevel.Length + "/".Length); + + subpathToTraverse = m_Subtree.Substring(startIndex); + } + else + { + subpathToTraverse = m_Subtree; + } + subpathToTraverse = subpathToTraverse.Trim('/'); + + bool excludeChildren = false; + if (subpathToTraverse.EndsWith(".mesh")) + { + subpathToTraverse = subpathToTraverse.Substring(0, subpathToTraverse.Length - ".mesh".Length); + excludeChildren = true; + } + if (node.name == subpathToTraverse) + { + // We're already at the right node + // No need to do anything + Debug.LogWarning($"Didn't expect to get here..."); + } + else + { + // - node will be null if not found + node = node.Find(subpathToTraverse); + } + + if (node != null) + { + if (excludeChildren) + { + foreach (Transform child in node) + { + Destroy(child.gameObject); + } + } + var newRoot = new GameObject(); + newRoot.transform.SetParent(transform); + switch (m_Model.GetLocation().GetLocationType()) + { + case Model.Location.Type.LocalFile: + newRoot.name = $"LocalFile:{m_Model.RelativePath}#{m_Subtree}"; + break; + case Model.Location.Type.IcosaAssetId: + newRoot.name = $"RemoteFile:{m_Model.AssetId}#{m_Subtree}"; + break; + case Model.Location.Type.Invalid: + throw new InvalidOperationException("Invalid model location type"); + } + m_ObjModelScript = newRoot.AddComponent(); + node.SetParent(newRoot.transform, worldPositionStays: true); + + oldRoot.gameObject.SetActive(false); // TODO destroy might fail on first load so also hide + Destroy(oldRoot.gameObject); + + m_ObjModelScript.Init(); + if (excludeChildren) + { + // Destroyed children aren't destroyed immediately, so we need to assign them manually + var mf = node.GetComponent(); + var smr = node.GetComponent(); + m_ObjModelScript.m_MeshChildren = mf != null ? new[] { mf } : Array.Empty(); + m_ObjModelScript.m_SkinnedMeshChildren = smr != null ? new[] { smr } : Array.Empty(); + } + + CloneInitialMaterials(null); + RecalculateColliderBounds(); + } + } + + public void RecalculateColliderBounds() + { + var widgetTransform = m_ObjModelScript.transform.parent; + + // Save the widget's original transform + var oldParent = widgetTransform.parent; + var oldPosition = widgetTransform.localPosition; + var oldRotation = widgetTransform.localRotation; + var oldScale = widgetTransform.localScale; + + // Move it to the origin + widgetTransform.SetParent(null); + widgetTransform.localPosition = Vector3.zero; + widgetTransform.localRotation = Quaternion.identity; + widgetTransform.localScale = Vector3.one; + + // Reset the collider gameobject transform + m_BoxCollider.transform.localPosition = Vector3.zero; + m_BoxCollider.transform.localRotation = Quaternion.identity; + m_BoxCollider.transform.localScale = Vector3.one; + + // Collect the renderers + var meshRenderers = m_ObjModelScript + .m_MeshChildren + .Select(x => x.GetComponent()); + var skinnedMeshRenderers = m_ObjModelScript.m_SkinnedMeshChildren; + + // Calculate the bounds + Bounds b = new Bounds(); + bool first = true; + var boundsList = meshRenderers.Select(x => x.bounds).ToList(); + boundsList.AddRange(skinnedMeshRenderers.Select(x => x.bounds)); + + for (var i = 0; i < boundsList.Count; i++) + { + var bounds = boundsList[i]; + + if (first) + { + b = bounds; + first = false; + } + else + { + b.Encapsulate(bounds); + } + } + + m_MeshBounds = b; + m_BoxCollider.transform.localPosition = m_MeshBounds.center; + m_BoxCollider.size = m_MeshBounds.size; + + // Restore the widget's original transform + widgetTransform.SetParent(oldParent); + widgetTransform.localPosition = oldPosition; + widgetTransform.localRotation = oldRotation; + widgetTransform.localScale = oldScale; + } + + public override float GetActivationScore(Vector3 vControllerPos, InputManager.ControllerName name) + { + Vector3 vInvTransformedPos = m_BoxCollider.transform.InverseTransformPoint(vControllerPos); + Vector3 vSize = m_BoxCollider.size * 0.5f; + float xDiff = vSize.x - Mathf.Abs(vInvTransformedPos.x); + float yDiff = vSize.y - Mathf.Abs(vInvTransformedPos.y); + float zDiff = vSize.z - Mathf.Abs(vInvTransformedPos.z); + if (xDiff > 0.0f && yDiff > 0.0f && zDiff > 0.0f) + { + float minSize = Mathf.Abs(m_Size) * + Mathf.Min(m_BoxCollider.size.x, Mathf.Min(m_BoxCollider.size.y, m_BoxCollider.size.z)); + return (xDiff / vSize.x + yDiff / vSize.y + zDiff / vSize.z) / 3 / (minSize + 1); + } + return -1.0f; + } + + private static Vector3 GetBoundsRatios(Bounds bounds) + { + float maxExtent = 0.001f; // epsilon to avoid division by zero + maxExtent = Mathf.Max(maxExtent, bounds.extents.x); + maxExtent = Mathf.Max(maxExtent, bounds.extents.y); + maxExtent = Mathf.Max(maxExtent, bounds.extents.z); + + return new Vector3( + bounds.extents.x / maxExtent, + bounds.extents.y / maxExtent, + bounds.extents.z / maxExtent); + } + + protected override void OnShow() + { + base.OnShow(); + + if (m_Model != null && m_Model.m_Valid) + { + SetSignedWidgetSize(0.0f); + } + + if (!m_LoadingFromSketch) + { + m_IntroAnimState = IntroAnimState.In; + Debug.Assert(!IsMoving(), "Shouldn't have velocity!"); + ClearVelocities(); + m_IntroAnimValue = 0.0f; + UpdateIntroAnim(); + } + else + { + m_IntroAnimState = IntroAnimState.On; + } + } + + protected override void OnUpdate() + { + // During transitions, scale up and down. + if (m_CurrentState == State.Hiding) + { + SetWidgetSizeAboutCenterOfMass(m_HideSize_CS * GetShowRatio()); + } + } + + protected override void UpdateIntroAnim() + { + base.UpdateIntroAnim(); + if (!m_LoadingFromSketch) + { + SetWidgetSizeAboutCenterOfMass(m_InitSize_CS * m_IntroAnimValue); + } + } + + protected override void UpdateScale() + { + if (this == null) return; // BreakModelApartCommand can destroy us + transform.localScale = Vector3.one * m_Size; + if (m_Model != null && m_Model.m_Valid) + { + m_BoxCollider.size = MeshBounds.size + m_ContainerBloat; + } + } + + private Bounds m_MeshBounds; + public Bounds MeshBounds + { + get + { + if (string.IsNullOrEmpty(m_Subtree)) + { + return m_Model.m_MeshBounds; + } + return m_MeshBounds; + } + } + + override protected void InitPin() + { + base.InitPin(); + // Move the pin closer to the center since the bounds around the mesh might not be very tight. + m_Pin.SetPenetrationScalar(.25f); + } + + public override void RegisterHighlight() + { +#if !(UNITY_ANDROID || UNITY_IOS) + if (m_ObjModelScript != null) + { + m_ObjModelScript.RegisterHighlight(); + return; + } +#endif + base.RegisterHighlight(); + } + + protected override void UnregisterHighlight() + { +#if !(UNITY_ANDROID || UNITY_IOS) + if (m_ObjModelScript != null) + { + m_ObjModelScript.UnregisterHighlight(); + return; + } +#endif + base.UnregisterHighlight(); + } + + public TrTransform GetSaveTransform() + { + var xf = TrTransform.FromLocalTransform(transform); + xf.scale = GetSignedWidgetSize(); + return xf; + } + + public override Vector2 GetWidgetSizeRange() + { + // m_Model can be null in the event we're pulling the model from Poly. + if (m_Model == null || !m_Model.m_Valid) + { + // Don't enforce a size range if we don't know the extents yet. + // It will be contrained when the model loads in and the bounds are known. + return new Vector2(float.MinValue, float.MaxValue); + } + float maxExtent = 2 * Mathf.Max(m_Model.m_MeshBounds.extents.x, + Mathf.Max(m_Model.m_MeshBounds.extents.y, m_Model.m_MeshBounds.extents.z)); + // If we created a widget with a model that doesn't have geo, we won't have calculated a + // bounds with great data. Protect against divide by zero. + if (maxExtent == 0.0f) + { + maxExtent = 1.0f; + } + return new Vector2(m_MinSize_CS / maxExtent, m_MaxSize_CS / maxExtent); + } + + /// This method is for use when loading widgets that use the pre-M13 file format, + /// which is normalized with respect to min and max size (ie: the transform is not "raw") + public void SetWidgetSizeNonRaw(float fScale) + { + Vector3 extents = m_Model.m_MeshBounds.extents; + float maxExtent = Mathf.Max(extents.x, Mathf.Max(extents.y, extents.z)); + // If we created a widget with a model that doesn't have geo, we won't have calculated a + // bounds with great data. Protect against divide by zero. + if (maxExtent == 0.0f) + { + maxExtent = 1.0f; + } + float sizeRatio = kInitialSizeMeters_RS / 2 / maxExtent; + SetSignedWidgetSize(fScale * sizeRatio * 10); + } + + + /// Updates the scale of the object, but with the center-of-scale + /// being the center of mass's origin, as opposed to the widget's origin. + /// Postconditions: + /// - GetWidgetSize() == size + /// - CenterOfMassPose_LS is unchanged (modulo precision issues) + protected void SetWidgetSizeAboutCenterOfMass(float size) + { + if (m_Size == size) { return; } + + // Use WithUnitScale because we want only the pos/rot difference + // Find delta such that delta * new = old + var oldCm_LS = WithUnitScale(CenterOfMassPose_LS); + m_Size = size; + UpdateScale(); + var newCm_LS = WithUnitScale(CenterOfMassPose_LS); + var delta_LS = oldCm_LS * newCm_LS.inverse; + if (CenterOfMassTransform == transform) + { + // Edge case when they are equal: delta_LS will only be approximately identity. + // Make it exactly identity for a smidge more accuracy + delta_LS = TrTransform.identity; + } + + LocalTransform = delta_LS * LocalTransform; + } + + /// I believe (but am not sure) that Media Library content loads synchronously, + /// and PAC content loads asynchronously. + public static async void CreateFromSaveData(TiltModels75 modelDatas) + { + Debug.AssertFormat(modelDatas.AssetId == null || modelDatas.FilePath == null, + "Model Data should not have an AssetID *and* a File Path"); + Debug.AssertFormat(!modelDatas.InSet_deprecated, + "InSet should have been removed at load time"); + + bool ok; + if (modelDatas.FilePath != null) + { + + Task okTask = CreateModelsFromRelativePath( + modelDatas.FilePath, modelDatas.Subtrees, + modelDatas.Transforms, modelDatas.RawTransforms, modelDatas.PinStates, + modelDatas.GroupIds, modelDatas.LayerIds); + ok = await okTask; + + } + else if (modelDatas.AssetId != null) + { + CreateModelsFromAssetId( + modelDatas.AssetId, modelDatas.Subtrees, + modelDatas.RawTransforms, modelDatas.PinStates, modelDatas.GroupIds, modelDatas.LayerIds); + ok = true; + } + else + { + Debug.LogError("Model Data doesn't contain an AssetID or File Path."); + ok = false; + } + + if (!ok) + { + ModelCatalog.m_Instance.AddMissingModel( + modelDatas.FilePath, modelDatas.Transforms, modelDatas.RawTransforms); + } + } + + /// I believe (but am not sure) that this is synchronous. + /// Returns false if the model can't be loaded -- in this case, caller is responsible + /// for creating the missing-model placeholder. + public static async Task CreateModelsFromRelativePath( + string relativePath, string[] subtrees, TrTransform[] xfs, TrTransform[] rawXfs, bool[] pinStates, uint[] groupIds, int[] layerIds) + { + // Verify model is loaded. Or, at least, has been tried to be loaded. + Model model = ModelCatalog.m_Instance.GetModel(relativePath); + if (model == null) { return false; } + + if (!model.m_Valid) + { + // Reload the model if it's not valid or if we're loading a subtree. + Task t = model.LoadModelAsync(); + await t; + } + if (!model.m_Valid) + { + return false; + } + + if (xfs != null) + { + // Pre M13 format + for (int i = 0; i < xfs.Length; ++i) + { + bool pin = (pinStates != null && i < pinStates.Length) ? pinStates[i] : true; + uint groupId = (groupIds != null && i < groupIds.Length) ? groupIds[i] : 0; + CreateModel(model, subtrees[i], xfs[i], pin, isNonRawTransform: true, groupId, 0); + } + } + if (rawXfs != null) + { + // Post M13 format + for (int i = 0; i < rawXfs.Length; ++i) + { + bool pin = (pinStates != null && i < pinStates.Length) ? pinStates[i] : true; + uint groupId = (groupIds != null && i < groupIds.Length) ? groupIds[i] : 0; + int layerId = (layerIds != null && i < layerIds.Length) ? layerIds[i] : 0; + CreateModel(model, subtrees[i], rawXfs[i], pin, isNonRawTransform: false, groupId, layerId); + } + } + return true; + } + + /// isNonRawTransform - true if the transform uses the pre-M13 meaning of transform.scale. + static void CreateModel(Model model, string subtree, TrTransform xf, bool pin, + bool isNonRawTransform, uint groupId, int layerId, string assetId = null) + { + + var modelWidget = Instantiate(WidgetManager.m_Instance.ModelWidgetPrefab) as ModelWidget; + modelWidget.transform.localPosition = xf.translation; + modelWidget.transform.localRotation = xf.rotation; + modelWidget.Model = model; + modelWidget.m_Subtree = subtree; + modelWidget.SyncHierarchyToSubtree(); + modelWidget.m_LoadingFromSketch = true; + modelWidget.Show(true, false); + if (isNonRawTransform) + { + modelWidget.SetWidgetSizeNonRaw(xf.scale); + modelWidget.transform.localPosition -= + xf.rotation * modelWidget.Model.m_MeshBounds.center * modelWidget.GetSignedWidgetSize(); + } + else + { + modelWidget.SetSignedWidgetSize(xf.scale); + } + TiltMeterScript.m_Instance.AdjustMeterWithWidget(modelWidget.GetTiltMeterCost(), up: true); + if (pin) + { + modelWidget.PinFromSave(); + } + + if (assetId != null && !model.m_Valid) + { + App.IcosaAssetCatalog.CatalogChanged += modelWidget.OnPacCatalogChanged; + modelWidget.m_PolyCallbackActive = true; + } + modelWidget.Group = App.GroupManager.GetGroupFromId(groupId); + modelWidget.SetCanvas(App.Scene.GetOrCreateLayer(layerId)); + } + + // Used when loading model assetIds from a serialized format (e.g. Tilt file). + static void CreateModelsFromAssetId(string assetId, string[] subtrees, TrTransform[] rawXfs, + bool[] pinStates, uint[] groupIds, int[] layerIds) + { + // Request model from Poly and if it doesn't exist, ask to load it. + Model model = App.IcosaAssetCatalog.GetModel(assetId); + if (model == null) + { + // This Model is transient; the Widget will replace it with a good Model from the PAC + // as soon as the PAC loads it. + model = new Model(Model.Location.IcosaAsset(assetId, null)); + } + if (!model.m_Valid) + { + App.IcosaAssetCatalog.RequestModelLoad(assetId, "widget"); + } + + // Create a widget for each transform. + for (int i = 0; i < rawXfs.Length; ++i) + { + bool pin = (i < pinStates.Length) ? pinStates[i] : true; + uint groupId = (groupIds != null && i < groupIds.Length) ? groupIds[i] : 0; + int layerId = (layerIds != null && i < layerIds.Length) ? layerIds[i] : 0; + CreateModel(model, subtrees[i], rawXfs[i], pin, isNonRawTransform: false, groupId, layerId, assetId); + } + } + + override public bool HasGPUIntersectionObject() + { + return m_ModelInstance != null; + } + + override public void SetGPUIntersectionObjectLayer(int layer) + { + HierarchyUtils.RecursivelySetLayer(m_ModelInstance, layer); + } + + override public void RestoreGPUIntersectionObjectLayer() + { + HierarchyUtils.RecursivelySetLayer(m_ModelInstance, m_BackupLayer); + } + + override public bool CanSnapToHome() + { + return m_Model.m_MeshBounds.center == Vector3.zero; + } + + public void AddSceneLightGizmos() + { + var lights = m_ObjModelScript.transform.GetComponentsInChildren(); + foreach (var light in lights) + { + // Probably not the right place to do it but we have to it somewhere + light.renderMode = LightRenderMode.ForceVertex; + Transform tr = Instantiate( + WidgetManager.m_Instance.SceneLightGizmoPrefab.transform, + light.transform + ); + var gizmo = tr.GetComponent(); + gizmo.SetupLightGizmos(light); + } + } + + public void UpdateBatchInfo() + { + // Set a new batchId on this model so it can be picked up in GPU intersections. + m_BatchId = GpuIntersector.GetNextBatchId(); + HierarchyUtils.RecursivelySetMaterialBatchID(m_ModelInstance, m_BatchId); + WidgetManager.m_Instance.AddWidgetToBatchMap(this, m_BatchId); + } + } +} // namespace TiltBrush diff --git a/Assets/Settings/Localization/Strings/Strings Shared Data.asset b/Assets/Settings/Localization/Strings/Strings Shared Data.asset index 4aaa38e1db..93ad6f41c4 100644 --- a/Assets/Settings/Localization/Strings/Strings Shared Data.asset +++ b/Assets/Settings/Localization/Strings/Strings Shared Data.asset @@ -11,7 +11,7 @@ MonoBehaviour: m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: 5b11a58205ec3474ca216360e9fa74a8, type: 3} m_Name: Strings Shared Data - m_EditorClassIdentifier: + m_EditorClassIdentifier: m_TableCollectionName: Strings m_TableCollectionNameGuidString: c84355079ab3f3e4f8f3812258805f86 m_Entries: @@ -3279,6 +3279,14 @@ MonoBehaviour: m_Key: CONTROLLER_HINT_THUMBPAD_BRUSHSIZE m_Metadata: m_Items: [] + - m_Id: 164911761917042688 + m_Key: POPUP_ACCOUNTS_ICOSAINFO_DESCRIPTION + m_Metadata: + m_Items: [] + - m_Id: 164911966586494976 + m_Key: POPUP_ACCOUNTS_ICOSAINFO_TITLE + m_Metadata: + m_Items: [] - m_Id: 176764812224364544 m_Key: BRUSH_PASSTHROUGHHULL m_Metadata: diff --git a/Assets/Settings/Localization/Strings/Strings_de.asset b/Assets/Settings/Localization/Strings/Strings_de.asset index e0259b2546..14d275f270 100644 --- a/Assets/Settings/Localization/Strings/Strings_de.asset +++ b/Assets/Settings/Localization/Strings/Strings_de.asset @@ -505,7 +505,7 @@ MonoBehaviour: m_Metadata: m_Items: [] - m_Id: 7691576060649472 - m_Localized: Poly-Bibliothek + m_Localized: Icosa-Bibliothek m_Metadata: m_Items: [] - m_Id: 7691821452599296 diff --git a/Assets/Settings/Localization/Strings/Strings_en.asset b/Assets/Settings/Localization/Strings/Strings_en.asset index 0c50b585da..29c7d3d42e 100644 --- a/Assets/Settings/Localization/Strings/Strings_en.asset +++ b/Assets/Settings/Localization/Strings/Strings_en.asset @@ -501,7 +501,7 @@ MonoBehaviour: m_Metadata: m_Items: [] - m_Id: 7691576060649472 - m_Localized: Poly Library + m_Localized: Icosa Library m_Metadata: m_Items: [] - m_Id: 7691821452599296 @@ -3462,6 +3462,16 @@ MonoBehaviour: for a step by step guide.' m_Metadata: m_Items: [] + - m_Id: 164911761917042688 + m_Localized: 'Sign in to an Icosa account to allow + + uploading to Icosa.' + m_Metadata: + m_Items: [] + - m_Id: 164911966586494976 + m_Localized: Share to Icosa + m_Metadata: + m_Items: [] - m_Id: 170004956477833216 m_Localized: Please give Open Brush file access to save your creations! m_Metadata: diff --git a/Assets/Settings/Localization/Strings/Strings_es.asset b/Assets/Settings/Localization/Strings/Strings_es.asset index 0aa94db064..ec0d2c56c0 100644 --- a/Assets/Settings/Localization/Strings/Strings_es.asset +++ b/Assets/Settings/Localization/Strings/Strings_es.asset @@ -501,7 +501,7 @@ MonoBehaviour: m_Metadata: m_Items: [] - m_Id: 7691576060649472 - m_Localized: Biblioteca de Poly + m_Localized: Biblioteca de Icosa m_Metadata: m_Items: [] - m_Id: 7691821452599296 diff --git a/Assets/Settings/Localization/Strings/Strings_fr.asset b/Assets/Settings/Localization/Strings/Strings_fr.asset index c0c7d234f0..98b9741f5c 100644 --- a/Assets/Settings/Localization/Strings/Strings_fr.asset +++ b/Assets/Settings/Localization/Strings/Strings_fr.asset @@ -503,7 +503,7 @@ MonoBehaviour: m_Metadata: m_Items: [] - m_Id: 7691576060649472 - m_Localized: "Biblioth\xE8que Poly" + m_Localized: "Biblioth\xE8que Icosa" m_Metadata: m_Items: [] - m_Id: 7691821452599296 diff --git a/Assets/Settings/Localization/Strings/Strings_ja.asset b/Assets/Settings/Localization/Strings/Strings_ja.asset index 4175e9eeb7..1fa386568b 100644 --- a/Assets/Settings/Localization/Strings/Strings_ja.asset +++ b/Assets/Settings/Localization/Strings/Strings_ja.asset @@ -500,7 +500,7 @@ MonoBehaviour: m_Metadata: m_Items: [] - m_Id: 7691576060649472 - m_Localized: "Poly\u30E9\u30A4\u30D6\u30E9\u30EA" + m_Localized: "Icosa\u30E9\u30A4\u30D6\u30E9\u30EA" m_Metadata: m_Items: [] - m_Id: 7691821452599296 diff --git a/Assets/Settings/Localization/Strings/Strings_ko.asset b/Assets/Settings/Localization/Strings/Strings_ko.asset index 1fdf5c1bfe..b2fa9793c0 100644 --- a/Assets/Settings/Localization/Strings/Strings_ko.asset +++ b/Assets/Settings/Localization/Strings/Strings_ko.asset @@ -497,7 +497,7 @@ MonoBehaviour: m_Metadata: m_Items: [] - m_Id: 7691576060649472 - m_Localized: "Poly \uB77C\uC774\uBE0C\uB7EC\uB9AC" + m_Localized: "Icosa \uB77C\uC774\uBE0C\uB7EC\uB9AC" m_Metadata: m_Items: [] - m_Id: 7691821452599296 diff --git a/Assets/Settings/Localization/Strings/Strings_zh.asset b/Assets/Settings/Localization/Strings/Strings_zh.asset index 801374490a..d9aa0ddef2 100644 --- a/Assets/Settings/Localization/Strings/Strings_zh.asset +++ b/Assets/Settings/Localization/Strings/Strings_zh.asset @@ -495,7 +495,7 @@ MonoBehaviour: m_Metadata: m_Items: [] - m_Id: 7691576060649472 - m_Localized: Poly Library + m_Localized: Icosa Library m_Metadata: m_Items: [] - m_Id: 7691821452599296 diff --git a/Assets/Textures/Trademarked/icosalogo.png b/Assets/Textures/Trademarked/icosalogo.png new file mode 100644 index 0000000000..ebfbcd2f5c Binary files /dev/null and b/Assets/Textures/Trademarked/icosalogo.png differ diff --git a/Assets/Textures/Trademarked/icosalogo.png.meta b/Assets/Textures/Trademarked/icosalogo.png.meta new file mode 100644 index 0000000000..09f33c87a4 --- /dev/null +++ b/Assets/Textures/Trademarked/icosalogo.png.meta @@ -0,0 +1,110 @@ +fileFormatVersion: 2 +guid: ca2b2689a21743448be1a5306c61e90b +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 9 + 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: 0 + 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 + platformSettings: + - serializedVersion: 2 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Android + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + vertices: [] + indices: + edges: [] + weights: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThirdParty/GlTF/GlTF_Globals.cs b/Assets/ThirdParty/GlTF/GlTF_Globals.cs index bf6d84af03..f4542c43d3 100644 --- a/Assets/ThirdParty/GlTF/GlTF_Globals.cs +++ b/Assets/ThirdParty/GlTF/GlTF_Globals.cs @@ -472,6 +472,8 @@ public void WriteNamedObject(string name, object value) { WriteNamedInt(name, longValue); } else if (value is string stringValue) { WriteNamedString(name, stringValue); + } else if (value is float floatValue) { + WriteNamedFloat(name, floatValue); } else if (value is ExportFileReference fileValue) { WriteNamedFile(name, fileValue); } else { diff --git a/Assets/ThirdParty/Org.OpenAPITools.meta b/Assets/ThirdParty/Org.OpenAPITools.meta new file mode 100644 index 0000000000..f5f2d8a446 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8c8c43a57fb9346828af74ee364b666b +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThirdParty/Org.OpenAPITools/Api.meta b/Assets/ThirdParty/Org.OpenAPITools/Api.meta new file mode 100644 index 0000000000..b2a63d5ebc --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Api.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6f344de6a19014b8980cf1826f8ddada +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThirdParty/Org.OpenAPITools/Api/AssetsApi.cs b/Assets/ThirdParty/Org.OpenAPITools/Api/AssetsApi.cs new file mode 100644 index 0000000000..c394faa073 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Api/AssetsApi.cs @@ -0,0 +1,1584 @@ +/* + * Icosa API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 0.1.0 + * Generated by: https://github.com/openapitools/openapi-generator.git + */ + + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Net; +using System.Net.Mime; +using Org.OpenAPITools.Client; +using Org.OpenAPITools.Model; + +namespace Org.OpenAPITools.Api +{ + + /// + /// Represents a collection of functions to interact with the API endpoints + /// + public interface IAssetsApiSync : IApiAccessor + { + #region Synchronous Operations + /// + /// Delete Asset + /// + /// Thrown when fails to make API call + /// + /// Object + Object DeleteAssetAssetsAssetDelete(int asset); + + /// + /// Delete Asset + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// ApiResponse of Object + ApiResponse DeleteAssetAssetsAssetDeleteWithHttpInfo(int asset); + /// + /// Get Asset + /// + /// Thrown when fails to make API call + /// + /// + /// Asset + Asset GetAssetAssetsUserurlAsseturlGet(string userurl, string asseturl); + + /// + /// Get Asset + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// + /// ApiResponse of Asset + ApiResponse GetAssetAssetsUserurlAsseturlGetWithHttpInfo(string userurl, string asseturl); + /// + /// Get Assets + /// + /// Thrown when fails to make API call + /// (optional, default to 20) + /// (optional, default to 0) + /// (optional, default to false) + /// (optional) + /// (optional) + /// (optional) + /// List<Asset> + List GetAssetsAssetsGet(int? results = default(int?), int? page = default(int?), bool? curated = default(bool?), string? name = default(string?), string? description = default(string?), string? ownername = default(string?)); + + /// + /// Get Assets + /// + /// + /// + /// + /// Thrown when fails to make API call + /// (optional, default to 20) + /// (optional, default to 0) + /// (optional, default to false) + /// (optional) + /// (optional) + /// (optional) + /// ApiResponse of List<Asset> + ApiResponse> GetAssetsAssetsGetWithHttpInfo(int? results = default(int?), int? page = default(int?), bool? curated = default(bool?), string? name = default(string?), string? description = default(string?), string? ownername = default(string?)); + /// + /// Get Id Asset + /// + /// Thrown when fails to make API call + /// + /// Asset + Asset GetIdAssetAssetsIdAssetGet(int asset); + + /// + /// Get Id Asset + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// ApiResponse of Asset + ApiResponse GetIdAssetAssetsIdAssetGetWithHttpInfo(int asset); + /// + /// Unpublish Asset + /// + /// Thrown when fails to make API call + /// + /// Object + Object UnpublishAssetAssetsAssetUnpublishPatch(int asset); + + /// + /// Unpublish Asset + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// ApiResponse of Object + ApiResponse UnpublishAssetAssetsAssetUnpublishPatchWithHttpInfo(int asset); + /// + /// Update Asset + /// + /// Thrown when fails to make API call + /// + /// (optional) + /// (optional) + /// (optional) + /// (optional) + /// (optional) + /// (optional) + /// Asset + Asset UpdateAssetAssetsAssetPatch(int asset, AssetPatchData? data = default(AssetPatchData?), string? name = default(string?), string? url = default(string?), string? description = default(string?), string? visibility = default(string?), System.IO.Stream? thumbnail = default(System.IO.Stream?)); + + /// + /// Update Asset + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// (optional) + /// (optional) + /// (optional) + /// (optional) + /// (optional) + /// (optional) + /// ApiResponse of Asset + ApiResponse UpdateAssetAssetsAssetPatchWithHttpInfo(int asset, AssetPatchData? data = default(AssetPatchData?), string? name = default(string?), string? url = default(string?), string? description = default(string?), string? visibility = default(string?), System.IO.Stream? thumbnail = default(System.IO.Stream?)); + /// + /// Upload New Assets + /// + /// Thrown when fails to make API call + /// + /// Object + Object UploadNewAssetsAssetsPost(List files); + + /// + /// Upload New Assets + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// ApiResponse of Object + ApiResponse UploadNewAssetsAssetsPostWithHttpInfo(List files); + #endregion Synchronous Operations + } + + /// + /// Represents a collection of functions to interact with the API endpoints + /// + public interface IAssetsApiAsync : IApiAccessor + { + #region Asynchronous Operations + /// + /// Delete Asset + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of Object + System.Threading.Tasks.Task DeleteAssetAssetsAssetDeleteAsync(int asset, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + + /// + /// Delete Asset + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of ApiResponse (Object) + System.Threading.Tasks.Task> DeleteAssetAssetsAssetDeleteWithHttpInfoAsync(int asset, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + /// + /// Get Asset + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// + /// Cancellation Token to cancel the request. + /// Task of Asset + System.Threading.Tasks.Task GetAssetAssetsUserurlAsseturlGetAsync(string userurl, string asseturl, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + + /// + /// Get Asset + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// + /// Cancellation Token to cancel the request. + /// Task of ApiResponse (Asset) + System.Threading.Tasks.Task> GetAssetAssetsUserurlAsseturlGetWithHttpInfoAsync(string userurl, string asseturl, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + /// + /// Get Assets + /// + /// + /// + /// + /// Thrown when fails to make API call + /// (optional, default to 20) + /// (optional, default to 0) + /// (optional, default to false) + /// (optional) + /// (optional) + /// (optional) + /// Cancellation Token to cancel the request. + /// Task of List<Asset> + System.Threading.Tasks.Task> GetAssetsAssetsGetAsync(int? results = default(int?), int? page = default(int?), bool? curated = default(bool?), string? name = default(string?), string? description = default(string?), string? ownername = default(string?), System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + + /// + /// Get Assets + /// + /// + /// + /// + /// Thrown when fails to make API call + /// (optional, default to 20) + /// (optional, default to 0) + /// (optional, default to false) + /// (optional) + /// (optional) + /// (optional) + /// Cancellation Token to cancel the request. + /// Task of ApiResponse (List<Asset>) + System.Threading.Tasks.Task>> GetAssetsAssetsGetWithHttpInfoAsync(int? results = default(int?), int? page = default(int?), bool? curated = default(bool?), string? name = default(string?), string? description = default(string?), string? ownername = default(string?), System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + /// + /// Get Id Asset + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of Asset + System.Threading.Tasks.Task GetIdAssetAssetsIdAssetGetAsync(int asset, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + + /// + /// Get Id Asset + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of ApiResponse (Asset) + System.Threading.Tasks.Task> GetIdAssetAssetsIdAssetGetWithHttpInfoAsync(int asset, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + /// + /// Unpublish Asset + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of Object + System.Threading.Tasks.Task UnpublishAssetAssetsAssetUnpublishPatchAsync(int asset, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + + /// + /// Unpublish Asset + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of ApiResponse (Object) + System.Threading.Tasks.Task> UnpublishAssetAssetsAssetUnpublishPatchWithHttpInfoAsync(int asset, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + /// + /// Update Asset + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// (optional) + /// (optional) + /// (optional) + /// (optional) + /// (optional) + /// (optional) + /// Cancellation Token to cancel the request. + /// Task of Asset + System.Threading.Tasks.Task UpdateAssetAssetsAssetPatchAsync(int asset, AssetPatchData? data = default(AssetPatchData?), string? name = default(string?), string? url = default(string?), string? description = default(string?), string? visibility = default(string?), System.IO.Stream? thumbnail = default(System.IO.Stream?), System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + + /// + /// Update Asset + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// (optional) + /// (optional) + /// (optional) + /// (optional) + /// (optional) + /// (optional) + /// Cancellation Token to cancel the request. + /// Task of ApiResponse (Asset) + System.Threading.Tasks.Task> UpdateAssetAssetsAssetPatchWithHttpInfoAsync(int asset, AssetPatchData? data = default(AssetPatchData?), string? name = default(string?), string? url = default(string?), string? description = default(string?), string? visibility = default(string?), System.IO.Stream? thumbnail = default(System.IO.Stream?), System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + /// + /// Upload New Assets + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of Object + System.Threading.Tasks.Task UploadNewAssetsAssetsPostAsync(List files, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + + /// + /// Upload New Assets + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of ApiResponse (Object) + System.Threading.Tasks.Task> UploadNewAssetsAssetsPostWithHttpInfoAsync(List files, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + #endregion Asynchronous Operations + } + + /// + /// Represents a collection of functions to interact with the API endpoints + /// + public interface IAssetsApi : IAssetsApiSync, IAssetsApiAsync + { + + } + + /// + /// Represents a collection of functions to interact with the API endpoints + /// + public partial class AssetsApi : IDisposable, IAssetsApi + { + private Org.OpenAPITools.Client.ExceptionFactory _exceptionFactory = (name, response) => null; + + /// + /// Initializes a new instance of the class. + /// **IMPORTANT** This will also create an instance of HttpClient, which is less than ideal. + /// It's better to reuse the HttpClient and HttpClientHandler. + /// + /// + public AssetsApi() : this((string)null) + { + } + + /// + /// Initializes a new instance of the class. + /// **IMPORTANT** This will also create an instance of HttpClient, which is less than ideal. + /// It's better to reuse the HttpClient and HttpClientHandler. + /// + /// The target service's base path in URL format. + /// + /// + public AssetsApi(string basePath) + { + this.Configuration = Org.OpenAPITools.Client.Configuration.MergeConfigurations( + Org.OpenAPITools.Client.GlobalConfiguration.Instance, + new Org.OpenAPITools.Client.Configuration { BasePath = basePath } + ); + this.ApiClient = new Org.OpenAPITools.Client.ApiClient(this.Configuration.BasePath); + this.Client = this.ApiClient; + this.AsynchronousClient = this.ApiClient; + this.ExceptionFactory = Org.OpenAPITools.Client.Configuration.DefaultExceptionFactory; + } + + /// + /// Initializes a new instance of the class using Configuration object. + /// **IMPORTANT** This will also create an instance of HttpClient, which is less than ideal. + /// It's better to reuse the HttpClient and HttpClientHandler. + /// + /// An instance of Configuration. + /// + /// + public AssetsApi(Org.OpenAPITools.Client.Configuration configuration) + { + if (configuration == null) throw new ArgumentNullException("configuration"); + + this.Configuration = Org.OpenAPITools.Client.Configuration.MergeConfigurations( + Org.OpenAPITools.Client.GlobalConfiguration.Instance, + configuration + ); + this.ApiClient = new Org.OpenAPITools.Client.ApiClient(this.Configuration.BasePath); + this.Client = this.ApiClient; + this.AsynchronousClient = this.ApiClient; + ExceptionFactory = Org.OpenAPITools.Client.Configuration.DefaultExceptionFactory; + } + + /// + /// Initializes a new instance of the class + /// using a Configuration object and client instance. + /// + /// The client interface for synchronous API access. + /// The client interface for asynchronous API access. + /// The configuration object. + /// + public AssetsApi(Org.OpenAPITools.Client.ISynchronousClient client, Org.OpenAPITools.Client.IAsynchronousClient asyncClient, Org.OpenAPITools.Client.IReadableConfiguration configuration) + { + if (client == null) throw new ArgumentNullException("client"); + if (asyncClient == null) throw new ArgumentNullException("asyncClient"); + if (configuration == null) throw new ArgumentNullException("configuration"); + + this.Client = client; + this.AsynchronousClient = asyncClient; + this.Configuration = configuration; + this.ExceptionFactory = Org.OpenAPITools.Client.Configuration.DefaultExceptionFactory; + } + + /// + /// Disposes resources if they were created by us + /// + public void Dispose() + { + this.ApiClient?.Dispose(); + } + + /// + /// Holds the ApiClient if created + /// + public Org.OpenAPITools.Client.ApiClient ApiClient { get; set; } = null; + + /// + /// The client for accessing this underlying API asynchronously. + /// + public Org.OpenAPITools.Client.IAsynchronousClient AsynchronousClient { get; set; } + + /// + /// The client for accessing this underlying API synchronously. + /// + public Org.OpenAPITools.Client.ISynchronousClient Client { get; set; } + + /// + /// Gets the base path of the API client. + /// + /// The base path + public string GetBasePath() + { + return this.Configuration.BasePath; + } + + /// + /// Gets or sets the configuration object + /// + /// An instance of the Configuration + public Org.OpenAPITools.Client.IReadableConfiguration Configuration { get; set; } + + /// + /// Provides a factory method hook for the creation of exceptions. + /// + public Org.OpenAPITools.Client.ExceptionFactory ExceptionFactory + { + get + { + if (_exceptionFactory != null && _exceptionFactory.GetInvocationList().Length > 1) + { + throw new InvalidOperationException("Multicast delegate for ExceptionFactory is unsupported."); + } + return _exceptionFactory; + } + set { _exceptionFactory = value; } + } + + /// + /// Delete Asset + /// + /// Thrown when fails to make API call + /// + /// Object + public Object DeleteAssetAssetsAssetDelete(int asset) + { + Org.OpenAPITools.Client.ApiResponse localVarResponse = DeleteAssetAssetsAssetDeleteWithHttpInfo(asset); + return localVarResponse.Data; + } + + /// + /// Delete Asset + /// + /// Thrown when fails to make API call + /// + /// ApiResponse of Object + public Org.OpenAPITools.Client.ApiResponse DeleteAssetAssetsAssetDeleteWithHttpInfo(int asset) + { + Org.OpenAPITools.Client.RequestOptions localVarRequestOptions = new Org.OpenAPITools.Client.RequestOptions(); + + string[] _contentTypes = new string[] { + }; + + // to determine the Accept header + string[] _accepts = new string[] { + "application/json" + }; + + var localVarContentType = Org.OpenAPITools.Client.ClientUtils.SelectHeaderContentType(_contentTypes); + if (localVarContentType != null) localVarRequestOptions.HeaderParameters.Add("Content-Type", localVarContentType); + + var localVarAccept = Org.OpenAPITools.Client.ClientUtils.SelectHeaderAccept(_accepts); + if (localVarAccept != null) localVarRequestOptions.HeaderParameters.Add("Accept", localVarAccept); + + localVarRequestOptions.PathParameters.Add("asset", Org.OpenAPITools.Client.ClientUtils.ParameterToString(asset)); // path parameter + + // authentication (OAuth2PasswordBearer) required + // oauth required + if (!string.IsNullOrEmpty(this.Configuration.AccessToken) && !localVarRequestOptions.HeaderParameters.ContainsKey("Authorization")) + { + localVarRequestOptions.HeaderParameters.Add("Authorization", "Bearer " + this.Configuration.AccessToken); + } + + // make the HTTP request + var localVarResponse = this.Client.Delete("/assets/{asset}", localVarRequestOptions, this.Configuration); + + if (this.ExceptionFactory != null) + { + Exception _exception = this.ExceptionFactory("DeleteAssetAssetsAssetDelete", localVarResponse); + if (_exception != null) throw _exception; + } + + return localVarResponse; + } + + /// + /// Delete Asset + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of Object + public async System.Threading.Tasks.Task DeleteAssetAssetsAssetDeleteAsync(int asset, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + var task = DeleteAssetAssetsAssetDeleteWithHttpInfoAsync(asset, cancellationToken); +#if UNITY_EDITOR || !UNITY_WEBGL + Org.OpenAPITools.Client.ApiResponse localVarResponse = await task.ConfigureAwait(false); +#else + Org.OpenAPITools.Client.ApiResponse localVarResponse = await task; +#endif + return localVarResponse.Data; + } + + /// + /// Delete Asset + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of ApiResponse (Object) + public async System.Threading.Tasks.Task> DeleteAssetAssetsAssetDeleteWithHttpInfoAsync(int asset, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + + Org.OpenAPITools.Client.RequestOptions localVarRequestOptions = new Org.OpenAPITools.Client.RequestOptions(); + + string[] _contentTypes = new string[] { + }; + + // to determine the Accept header + string[] _accepts = new string[] { + "application/json" + }; + + + var localVarContentType = Org.OpenAPITools.Client.ClientUtils.SelectHeaderContentType(_contentTypes); + if (localVarContentType != null) localVarRequestOptions.HeaderParameters.Add("Content-Type", localVarContentType); + + var localVarAccept = Org.OpenAPITools.Client.ClientUtils.SelectHeaderAccept(_accepts); + if (localVarAccept != null) localVarRequestOptions.HeaderParameters.Add("Accept", localVarAccept); + + localVarRequestOptions.PathParameters.Add("asset", Org.OpenAPITools.Client.ClientUtils.ParameterToString(asset)); // path parameter + + // authentication (OAuth2PasswordBearer) required + // oauth required + if (!string.IsNullOrEmpty(this.Configuration.AccessToken) && !localVarRequestOptions.HeaderParameters.ContainsKey("Authorization")) + { + localVarRequestOptions.HeaderParameters.Add("Authorization", "Bearer " + this.Configuration.AccessToken); + } + + // make the HTTP request + + var task = this.AsynchronousClient.DeleteAsync("/assets/{asset}", localVarRequestOptions, this.Configuration, cancellationToken); + +#if UNITY_EDITOR || !UNITY_WEBGL + var localVarResponse = await task.ConfigureAwait(false); +#else + var localVarResponse = await task; +#endif + + if (this.ExceptionFactory != null) + { + Exception _exception = this.ExceptionFactory("DeleteAssetAssetsAssetDelete", localVarResponse); + if (_exception != null) throw _exception; + } + + return localVarResponse; + } + + /// + /// Get Asset + /// + /// Thrown when fails to make API call + /// + /// + /// Asset + public Asset GetAssetAssetsUserurlAsseturlGet(string userurl, string asseturl) + { + Org.OpenAPITools.Client.ApiResponse localVarResponse = GetAssetAssetsUserurlAsseturlGetWithHttpInfo(userurl, asseturl); + return localVarResponse.Data; + } + + /// + /// Get Asset + /// + /// Thrown when fails to make API call + /// + /// + /// ApiResponse of Asset + public Org.OpenAPITools.Client.ApiResponse GetAssetAssetsUserurlAsseturlGetWithHttpInfo(string userurl, string asseturl) + { + // verify the required parameter 'userurl' is set + if (userurl == null) + throw new Org.OpenAPITools.Client.ApiException(400, "Missing required parameter 'userurl' when calling AssetsApi->GetAssetAssetsUserurlAsseturlGet"); + + // verify the required parameter 'asseturl' is set + if (asseturl == null) + throw new Org.OpenAPITools.Client.ApiException(400, "Missing required parameter 'asseturl' when calling AssetsApi->GetAssetAssetsUserurlAsseturlGet"); + + Org.OpenAPITools.Client.RequestOptions localVarRequestOptions = new Org.OpenAPITools.Client.RequestOptions(); + + string[] _contentTypes = new string[] { + }; + + // to determine the Accept header + string[] _accepts = new string[] { + "application/json" + }; + + var localVarContentType = Org.OpenAPITools.Client.ClientUtils.SelectHeaderContentType(_contentTypes); + if (localVarContentType != null) localVarRequestOptions.HeaderParameters.Add("Content-Type", localVarContentType); + + var localVarAccept = Org.OpenAPITools.Client.ClientUtils.SelectHeaderAccept(_accepts); + if (localVarAccept != null) localVarRequestOptions.HeaderParameters.Add("Accept", localVarAccept); + + localVarRequestOptions.PathParameters.Add("userurl", Org.OpenAPITools.Client.ClientUtils.ParameterToString(userurl)); // path parameter + localVarRequestOptions.PathParameters.Add("asseturl", Org.OpenAPITools.Client.ClientUtils.ParameterToString(asseturl)); // path parameter + + // authentication (OAuth2PasswordBearer) required + // oauth required + if (!string.IsNullOrEmpty(this.Configuration.AccessToken) && !localVarRequestOptions.HeaderParameters.ContainsKey("Authorization")) + { + localVarRequestOptions.HeaderParameters.Add("Authorization", "Bearer " + this.Configuration.AccessToken); + } + + // make the HTTP request + var localVarResponse = this.Client.Get("/assets/{userurl}/{asseturl}", localVarRequestOptions, this.Configuration); + + if (this.ExceptionFactory != null) + { + Exception _exception = this.ExceptionFactory("GetAssetAssetsUserurlAsseturlGet", localVarResponse); + if (_exception != null) throw _exception; + } + + return localVarResponse; + } + + /// + /// Get Asset + /// + /// Thrown when fails to make API call + /// + /// + /// Cancellation Token to cancel the request. + /// Task of Asset + public async System.Threading.Tasks.Task GetAssetAssetsUserurlAsseturlGetAsync(string userurl, string asseturl, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + var task = GetAssetAssetsUserurlAsseturlGetWithHttpInfoAsync(userurl, asseturl, cancellationToken); +#if UNITY_EDITOR || !UNITY_WEBGL + Org.OpenAPITools.Client.ApiResponse localVarResponse = await task.ConfigureAwait(false); +#else + Org.OpenAPITools.Client.ApiResponse localVarResponse = await task; +#endif + return localVarResponse.Data; + } + + /// + /// Get Asset + /// + /// Thrown when fails to make API call + /// + /// + /// Cancellation Token to cancel the request. + /// Task of ApiResponse (Asset) + public async System.Threading.Tasks.Task> GetAssetAssetsUserurlAsseturlGetWithHttpInfoAsync(string userurl, string asseturl, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + // verify the required parameter 'userurl' is set + if (userurl == null) + throw new Org.OpenAPITools.Client.ApiException(400, "Missing required parameter 'userurl' when calling AssetsApi->GetAssetAssetsUserurlAsseturlGet"); + + // verify the required parameter 'asseturl' is set + if (asseturl == null) + throw new Org.OpenAPITools.Client.ApiException(400, "Missing required parameter 'asseturl' when calling AssetsApi->GetAssetAssetsUserurlAsseturlGet"); + + + Org.OpenAPITools.Client.RequestOptions localVarRequestOptions = new Org.OpenAPITools.Client.RequestOptions(); + + string[] _contentTypes = new string[] { + }; + + // to determine the Accept header + string[] _accepts = new string[] { + "application/json" + }; + + + var localVarContentType = Org.OpenAPITools.Client.ClientUtils.SelectHeaderContentType(_contentTypes); + if (localVarContentType != null) localVarRequestOptions.HeaderParameters.Add("Content-Type", localVarContentType); + + var localVarAccept = Org.OpenAPITools.Client.ClientUtils.SelectHeaderAccept(_accepts); + if (localVarAccept != null) localVarRequestOptions.HeaderParameters.Add("Accept", localVarAccept); + + localVarRequestOptions.PathParameters.Add("userurl", Org.OpenAPITools.Client.ClientUtils.ParameterToString(userurl)); // path parameter + localVarRequestOptions.PathParameters.Add("asseturl", Org.OpenAPITools.Client.ClientUtils.ParameterToString(asseturl)); // path parameter + + // authentication (OAuth2PasswordBearer) required + // oauth required + if (!string.IsNullOrEmpty(this.Configuration.AccessToken) && !localVarRequestOptions.HeaderParameters.ContainsKey("Authorization")) + { + localVarRequestOptions.HeaderParameters.Add("Authorization", "Bearer " + this.Configuration.AccessToken); + } + + // make the HTTP request + + var task = this.AsynchronousClient.GetAsync("/assets/{userurl}/{asseturl}", localVarRequestOptions, this.Configuration, cancellationToken); + +#if UNITY_EDITOR || !UNITY_WEBGL + var localVarResponse = await task.ConfigureAwait(false); +#else + var localVarResponse = await task; +#endif + + if (this.ExceptionFactory != null) + { + Exception _exception = this.ExceptionFactory("GetAssetAssetsUserurlAsseturlGet", localVarResponse); + if (_exception != null) throw _exception; + } + + return localVarResponse; + } + + /// + /// Get Assets + /// + /// Thrown when fails to make API call + /// (optional, default to 20) + /// (optional, default to 0) + /// (optional, default to false) + /// (optional) + /// (optional) + /// (optional) + /// List<Asset> + public List GetAssetsAssetsGet(int? results = default(int?), int? page = default(int?), bool? curated = default(bool?), string? name = default(string?), string? description = default(string?), string? ownername = default(string?)) + { + Org.OpenAPITools.Client.ApiResponse> localVarResponse = GetAssetsAssetsGetWithHttpInfo(results, page, curated, name, description, ownername); + return localVarResponse.Data; + } + + /// + /// Get Assets + /// + /// Thrown when fails to make API call + /// (optional, default to 20) + /// (optional, default to 0) + /// (optional, default to false) + /// (optional) + /// (optional) + /// (optional) + /// ApiResponse of List<Asset> + public Org.OpenAPITools.Client.ApiResponse> GetAssetsAssetsGetWithHttpInfo(int? results = default(int?), int? page = default(int?), bool? curated = default(bool?), string? name = default(string?), string? description = default(string?), string? ownername = default(string?)) + { + Org.OpenAPITools.Client.RequestOptions localVarRequestOptions = new Org.OpenAPITools.Client.RequestOptions(); + + string[] _contentTypes = new string[] { + }; + + // to determine the Accept header + string[] _accepts = new string[] { + "application/json" + }; + + var localVarContentType = Org.OpenAPITools.Client.ClientUtils.SelectHeaderContentType(_contentTypes); + if (localVarContentType != null) localVarRequestOptions.HeaderParameters.Add("Content-Type", localVarContentType); + + var localVarAccept = Org.OpenAPITools.Client.ClientUtils.SelectHeaderAccept(_accepts); + if (localVarAccept != null) localVarRequestOptions.HeaderParameters.Add("Accept", localVarAccept); + + if (results != null) + { + localVarRequestOptions.QueryParameters.Add(Org.OpenAPITools.Client.ClientUtils.ParameterToMultiMap("", "results", results)); + } + if (page != null) + { + localVarRequestOptions.QueryParameters.Add(Org.OpenAPITools.Client.ClientUtils.ParameterToMultiMap("", "page", page)); + } + if (curated != null) + { + localVarRequestOptions.QueryParameters.Add(Org.OpenAPITools.Client.ClientUtils.ParameterToMultiMap("", "curated", curated)); + } + if (name != null) + { + localVarRequestOptions.QueryParameters.Add(Org.OpenAPITools.Client.ClientUtils.ParameterToMultiMap("", "name", name)); + } + if (description != null) + { + localVarRequestOptions.QueryParameters.Add(Org.OpenAPITools.Client.ClientUtils.ParameterToMultiMap("", "description", description)); + } + if (ownername != null) + { + localVarRequestOptions.QueryParameters.Add(Org.OpenAPITools.Client.ClientUtils.ParameterToMultiMap("", "ownername", ownername)); + } + + + // make the HTTP request + var localVarResponse = this.Client.Get>("/assets", localVarRequestOptions, this.Configuration); + + if (this.ExceptionFactory != null) + { + Exception _exception = this.ExceptionFactory("GetAssetsAssetsGet", localVarResponse); + if (_exception != null) throw _exception; + } + + return localVarResponse; + } + + /// + /// Get Assets + /// + /// Thrown when fails to make API call + /// (optional, default to 20) + /// (optional, default to 0) + /// (optional, default to false) + /// (optional) + /// (optional) + /// (optional) + /// Cancellation Token to cancel the request. + /// Task of List<Asset> + public async System.Threading.Tasks.Task> GetAssetsAssetsGetAsync(int? results = default(int?), int? page = default(int?), bool? curated = default(bool?), string? name = default(string?), string? description = default(string?), string? ownername = default(string?), System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + var task = GetAssetsAssetsGetWithHttpInfoAsync(results, page, curated, name, description, ownername, cancellationToken); +#if UNITY_EDITOR || !UNITY_WEBGL + Org.OpenAPITools.Client.ApiResponse> localVarResponse = await task.ConfigureAwait(false); +#else + Org.OpenAPITools.Client.ApiResponse> localVarResponse = await task; +#endif + return localVarResponse.Data; + } + + /// + /// Get Assets + /// + /// Thrown when fails to make API call + /// (optional, default to 20) + /// (optional, default to 0) + /// (optional, default to false) + /// (optional) + /// (optional) + /// (optional) + /// Cancellation Token to cancel the request. + /// Task of ApiResponse (List<Asset>) + public async System.Threading.Tasks.Task>> GetAssetsAssetsGetWithHttpInfoAsync(int? results = default(int?), int? page = default(int?), bool? curated = default(bool?), string? name = default(string?), string? description = default(string?), string? ownername = default(string?), System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + + Org.OpenAPITools.Client.RequestOptions localVarRequestOptions = new Org.OpenAPITools.Client.RequestOptions(); + + string[] _contentTypes = new string[] { + }; + + // to determine the Accept header + string[] _accepts = new string[] { + "application/json" + }; + + + var localVarContentType = Org.OpenAPITools.Client.ClientUtils.SelectHeaderContentType(_contentTypes); + if (localVarContentType != null) localVarRequestOptions.HeaderParameters.Add("Content-Type", localVarContentType); + + var localVarAccept = Org.OpenAPITools.Client.ClientUtils.SelectHeaderAccept(_accepts); + if (localVarAccept != null) localVarRequestOptions.HeaderParameters.Add("Accept", localVarAccept); + + if (results != null) + { + localVarRequestOptions.QueryParameters.Add(Org.OpenAPITools.Client.ClientUtils.ParameterToMultiMap("", "results", results)); + } + if (page != null) + { + localVarRequestOptions.QueryParameters.Add(Org.OpenAPITools.Client.ClientUtils.ParameterToMultiMap("", "page", page)); + } + if (curated != null) + { + localVarRequestOptions.QueryParameters.Add(Org.OpenAPITools.Client.ClientUtils.ParameterToMultiMap("", "curated", curated)); + } + if (name != null) + { + localVarRequestOptions.QueryParameters.Add(Org.OpenAPITools.Client.ClientUtils.ParameterToMultiMap("", "name", name)); + } + if (description != null) + { + localVarRequestOptions.QueryParameters.Add(Org.OpenAPITools.Client.ClientUtils.ParameterToMultiMap("", "description", description)); + } + if (ownername != null) + { + localVarRequestOptions.QueryParameters.Add(Org.OpenAPITools.Client.ClientUtils.ParameterToMultiMap("", "ownername", ownername)); + } + + + // make the HTTP request + + var task = this.AsynchronousClient.GetAsync>("/assets", localVarRequestOptions, this.Configuration, cancellationToken); + +#if UNITY_EDITOR || !UNITY_WEBGL + var localVarResponse = await task.ConfigureAwait(false); +#else + var localVarResponse = await task; +#endif + + if (this.ExceptionFactory != null) + { + Exception _exception = this.ExceptionFactory("GetAssetsAssetsGet", localVarResponse); + if (_exception != null) throw _exception; + } + + return localVarResponse; + } + + /// + /// Get Id Asset + /// + /// Thrown when fails to make API call + /// + /// Asset + public Asset GetIdAssetAssetsIdAssetGet(int asset) + { + Org.OpenAPITools.Client.ApiResponse localVarResponse = GetIdAssetAssetsIdAssetGetWithHttpInfo(asset); + return localVarResponse.Data; + } + + /// + /// Get Id Asset + /// + /// Thrown when fails to make API call + /// + /// ApiResponse of Asset + public Org.OpenAPITools.Client.ApiResponse GetIdAssetAssetsIdAssetGetWithHttpInfo(int asset) + { + Org.OpenAPITools.Client.RequestOptions localVarRequestOptions = new Org.OpenAPITools.Client.RequestOptions(); + + string[] _contentTypes = new string[] { + }; + + // to determine the Accept header + string[] _accepts = new string[] { + "application/json" + }; + + var localVarContentType = Org.OpenAPITools.Client.ClientUtils.SelectHeaderContentType(_contentTypes); + if (localVarContentType != null) localVarRequestOptions.HeaderParameters.Add("Content-Type", localVarContentType); + + var localVarAccept = Org.OpenAPITools.Client.ClientUtils.SelectHeaderAccept(_accepts); + if (localVarAccept != null) localVarRequestOptions.HeaderParameters.Add("Accept", localVarAccept); + + localVarRequestOptions.PathParameters.Add("asset", Org.OpenAPITools.Client.ClientUtils.ParameterToString(asset)); // path parameter + + // authentication (OAuth2PasswordBearer) required + // oauth required + if (!string.IsNullOrEmpty(this.Configuration.AccessToken) && !localVarRequestOptions.HeaderParameters.ContainsKey("Authorization")) + { + localVarRequestOptions.HeaderParameters.Add("Authorization", "Bearer " + this.Configuration.AccessToken); + } + + // make the HTTP request + var localVarResponse = this.Client.Get("/assets/id/{asset}", localVarRequestOptions, this.Configuration); + + if (this.ExceptionFactory != null) + { + Exception _exception = this.ExceptionFactory("GetIdAssetAssetsIdAssetGet", localVarResponse); + if (_exception != null) throw _exception; + } + + return localVarResponse; + } + + /// + /// Get Id Asset + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of Asset + public async System.Threading.Tasks.Task GetIdAssetAssetsIdAssetGetAsync(int asset, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + var task = GetIdAssetAssetsIdAssetGetWithHttpInfoAsync(asset, cancellationToken); +#if UNITY_EDITOR || !UNITY_WEBGL + Org.OpenAPITools.Client.ApiResponse localVarResponse = await task.ConfigureAwait(false); +#else + Org.OpenAPITools.Client.ApiResponse localVarResponse = await task; +#endif + return localVarResponse.Data; + } + + /// + /// Get Id Asset + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of ApiResponse (Asset) + public async System.Threading.Tasks.Task> GetIdAssetAssetsIdAssetGetWithHttpInfoAsync(int asset, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + + Org.OpenAPITools.Client.RequestOptions localVarRequestOptions = new Org.OpenAPITools.Client.RequestOptions(); + + string[] _contentTypes = new string[] { + }; + + // to determine the Accept header + string[] _accepts = new string[] { + "application/json" + }; + + + var localVarContentType = Org.OpenAPITools.Client.ClientUtils.SelectHeaderContentType(_contentTypes); + if (localVarContentType != null) localVarRequestOptions.HeaderParameters.Add("Content-Type", localVarContentType); + + var localVarAccept = Org.OpenAPITools.Client.ClientUtils.SelectHeaderAccept(_accepts); + if (localVarAccept != null) localVarRequestOptions.HeaderParameters.Add("Accept", localVarAccept); + + localVarRequestOptions.PathParameters.Add("asset", Org.OpenAPITools.Client.ClientUtils.ParameterToString(asset)); // path parameter + + // authentication (OAuth2PasswordBearer) required + // oauth required + if (!string.IsNullOrEmpty(this.Configuration.AccessToken) && !localVarRequestOptions.HeaderParameters.ContainsKey("Authorization")) + { + localVarRequestOptions.HeaderParameters.Add("Authorization", "Bearer " + this.Configuration.AccessToken); + } + + // make the HTTP request + + var task = this.AsynchronousClient.GetAsync("/assets/id/{asset}", localVarRequestOptions, this.Configuration, cancellationToken); + +#if UNITY_EDITOR || !UNITY_WEBGL + var localVarResponse = await task.ConfigureAwait(false); +#else + var localVarResponse = await task; +#endif + + if (this.ExceptionFactory != null) + { + Exception _exception = this.ExceptionFactory("GetIdAssetAssetsIdAssetGet", localVarResponse); + if (_exception != null) throw _exception; + } + + return localVarResponse; + } + + /// + /// Unpublish Asset + /// + /// Thrown when fails to make API call + /// + /// Object + public Object UnpublishAssetAssetsAssetUnpublishPatch(int asset) + { + Org.OpenAPITools.Client.ApiResponse localVarResponse = UnpublishAssetAssetsAssetUnpublishPatchWithHttpInfo(asset); + return localVarResponse.Data; + } + + /// + /// Unpublish Asset + /// + /// Thrown when fails to make API call + /// + /// ApiResponse of Object + public Org.OpenAPITools.Client.ApiResponse UnpublishAssetAssetsAssetUnpublishPatchWithHttpInfo(int asset) + { + Org.OpenAPITools.Client.RequestOptions localVarRequestOptions = new Org.OpenAPITools.Client.RequestOptions(); + + string[] _contentTypes = new string[] { + }; + + // to determine the Accept header + string[] _accepts = new string[] { + "application/json" + }; + + var localVarContentType = Org.OpenAPITools.Client.ClientUtils.SelectHeaderContentType(_contentTypes); + if (localVarContentType != null) localVarRequestOptions.HeaderParameters.Add("Content-Type", localVarContentType); + + var localVarAccept = Org.OpenAPITools.Client.ClientUtils.SelectHeaderAccept(_accepts); + if (localVarAccept != null) localVarRequestOptions.HeaderParameters.Add("Accept", localVarAccept); + + localVarRequestOptions.PathParameters.Add("asset", Org.OpenAPITools.Client.ClientUtils.ParameterToString(asset)); // path parameter + + // authentication (OAuth2PasswordBearer) required + // oauth required + if (!string.IsNullOrEmpty(this.Configuration.AccessToken) && !localVarRequestOptions.HeaderParameters.ContainsKey("Authorization")) + { + localVarRequestOptions.HeaderParameters.Add("Authorization", "Bearer " + this.Configuration.AccessToken); + } + + // make the HTTP request + var localVarResponse = this.Client.Patch("/assets/{asset}/unpublish", localVarRequestOptions, this.Configuration); + + if (this.ExceptionFactory != null) + { + Exception _exception = this.ExceptionFactory("UnpublishAssetAssetsAssetUnpublishPatch", localVarResponse); + if (_exception != null) throw _exception; + } + + return localVarResponse; + } + + /// + /// Unpublish Asset + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of Object + public async System.Threading.Tasks.Task UnpublishAssetAssetsAssetUnpublishPatchAsync(int asset, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + var task = UnpublishAssetAssetsAssetUnpublishPatchWithHttpInfoAsync(asset, cancellationToken); +#if UNITY_EDITOR || !UNITY_WEBGL + Org.OpenAPITools.Client.ApiResponse localVarResponse = await task.ConfigureAwait(false); +#else + Org.OpenAPITools.Client.ApiResponse localVarResponse = await task; +#endif + return localVarResponse.Data; + } + + /// + /// Unpublish Asset + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of ApiResponse (Object) + public async System.Threading.Tasks.Task> UnpublishAssetAssetsAssetUnpublishPatchWithHttpInfoAsync(int asset, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + + Org.OpenAPITools.Client.RequestOptions localVarRequestOptions = new Org.OpenAPITools.Client.RequestOptions(); + + string[] _contentTypes = new string[] { + }; + + // to determine the Accept header + string[] _accepts = new string[] { + "application/json" + }; + + + var localVarContentType = Org.OpenAPITools.Client.ClientUtils.SelectHeaderContentType(_contentTypes); + if (localVarContentType != null) localVarRequestOptions.HeaderParameters.Add("Content-Type", localVarContentType); + + var localVarAccept = Org.OpenAPITools.Client.ClientUtils.SelectHeaderAccept(_accepts); + if (localVarAccept != null) localVarRequestOptions.HeaderParameters.Add("Accept", localVarAccept); + + localVarRequestOptions.PathParameters.Add("asset", Org.OpenAPITools.Client.ClientUtils.ParameterToString(asset)); // path parameter + + // authentication (OAuth2PasswordBearer) required + // oauth required + if (!string.IsNullOrEmpty(this.Configuration.AccessToken) && !localVarRequestOptions.HeaderParameters.ContainsKey("Authorization")) + { + localVarRequestOptions.HeaderParameters.Add("Authorization", "Bearer " + this.Configuration.AccessToken); + } + + // make the HTTP request + + var task = this.AsynchronousClient.PatchAsync("/assets/{asset}/unpublish", localVarRequestOptions, this.Configuration, cancellationToken); + +#if UNITY_EDITOR || !UNITY_WEBGL + var localVarResponse = await task.ConfigureAwait(false); +#else + var localVarResponse = await task; +#endif + + if (this.ExceptionFactory != null) + { + Exception _exception = this.ExceptionFactory("UnpublishAssetAssetsAssetUnpublishPatch", localVarResponse); + if (_exception != null) throw _exception; + } + + return localVarResponse; + } + + /// + /// Update Asset + /// + /// Thrown when fails to make API call + /// + /// (optional) + /// (optional) + /// (optional) + /// (optional) + /// (optional) + /// (optional) + /// Asset + public Asset UpdateAssetAssetsAssetPatch(int asset, AssetPatchData? data = default(AssetPatchData?), string? name = default(string?), string? url = default(string?), string? description = default(string?), string? visibility = default(string?), System.IO.Stream? thumbnail = default(System.IO.Stream?)) + { + Org.OpenAPITools.Client.ApiResponse localVarResponse = UpdateAssetAssetsAssetPatchWithHttpInfo(asset, data, name, url, description, visibility, thumbnail); + return localVarResponse.Data; + } + + /// + /// Update Asset + /// + /// Thrown when fails to make API call + /// + /// (optional) + /// (optional) + /// (optional) + /// (optional) + /// (optional) + /// (optional) + /// ApiResponse of Asset + public Org.OpenAPITools.Client.ApiResponse UpdateAssetAssetsAssetPatchWithHttpInfo(int asset, AssetPatchData? data = default(AssetPatchData?), string? name = default(string?), string? url = default(string?), string? description = default(string?), string? visibility = default(string?), System.IO.Stream? thumbnail = default(System.IO.Stream?)) + { + Org.OpenAPITools.Client.RequestOptions localVarRequestOptions = new Org.OpenAPITools.Client.RequestOptions(); + + string[] _contentTypes = new string[] { + "multipart/form-data" + }; + + // to determine the Accept header + string[] _accepts = new string[] { + "application/json" + }; + + var localVarContentType = Org.OpenAPITools.Client.ClientUtils.SelectHeaderContentType(_contentTypes); + if (localVarContentType != null) localVarRequestOptions.HeaderParameters.Add("Content-Type", localVarContentType); + + var localVarAccept = Org.OpenAPITools.Client.ClientUtils.SelectHeaderAccept(_accepts); + if (localVarAccept != null) localVarRequestOptions.HeaderParameters.Add("Accept", localVarAccept); + + localVarRequestOptions.PathParameters.Add("asset", Org.OpenAPITools.Client.ClientUtils.ParameterToString(asset)); // path parameter + if (data != null) + { + localVarRequestOptions.FormParameters.Add("data", Org.OpenAPITools.Client.ClientUtils.ParameterToString(data)); // form parameter + } + if (name != null) + { + localVarRequestOptions.FormParameters.Add("name", Org.OpenAPITools.Client.ClientUtils.ParameterToString(name)); // form parameter + } + if (url != null) + { + localVarRequestOptions.FormParameters.Add("url", Org.OpenAPITools.Client.ClientUtils.ParameterToString(url)); // form parameter + } + if (description != null) + { + localVarRequestOptions.FormParameters.Add("description", Org.OpenAPITools.Client.ClientUtils.ParameterToString(description)); // form parameter + } + if (visibility != null) + { + localVarRequestOptions.FormParameters.Add("visibility", Org.OpenAPITools.Client.ClientUtils.ParameterToString(visibility)); // form parameter + } + if (thumbnail != null) + { + } + + // authentication (OAuth2PasswordBearer) required + // oauth required + if (!string.IsNullOrEmpty(this.Configuration.AccessToken) && !localVarRequestOptions.HeaderParameters.ContainsKey("Authorization")) + { + localVarRequestOptions.HeaderParameters.Add("Authorization", "Bearer " + this.Configuration.AccessToken); + } + + // make the HTTP request + var localVarResponse = this.Client.Patch("/assets/{asset}", localVarRequestOptions, this.Configuration); + + if (this.ExceptionFactory != null) + { + Exception _exception = this.ExceptionFactory("UpdateAssetAssetsAssetPatch", localVarResponse); + if (_exception != null) throw _exception; + } + + return localVarResponse; + } + + /// + /// Update Asset + /// + /// Thrown when fails to make API call + /// + /// (optional) + /// (optional) + /// (optional) + /// (optional) + /// (optional) + /// (optional) + /// Cancellation Token to cancel the request. + /// Task of Asset + public async System.Threading.Tasks.Task UpdateAssetAssetsAssetPatchAsync(int asset, AssetPatchData? data = default(AssetPatchData?), string? name = default(string?), string? url = default(string?), string? description = default(string?), string? visibility = default(string?), System.IO.Stream? thumbnail = default(System.IO.Stream?), System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + var task = UpdateAssetAssetsAssetPatchWithHttpInfoAsync(asset, data, name, url, description, visibility, thumbnail, cancellationToken); +#if UNITY_EDITOR || !UNITY_WEBGL + Org.OpenAPITools.Client.ApiResponse localVarResponse = await task.ConfigureAwait(false); +#else + Org.OpenAPITools.Client.ApiResponse localVarResponse = await task; +#endif + return localVarResponse.Data; + } + + /// + /// Update Asset + /// + /// Thrown when fails to make API call + /// + /// (optional) + /// (optional) + /// (optional) + /// (optional) + /// (optional) + /// (optional) + /// Cancellation Token to cancel the request. + /// Task of ApiResponse (Asset) + public async System.Threading.Tasks.Task> UpdateAssetAssetsAssetPatchWithHttpInfoAsync(int asset, AssetPatchData? data = default(AssetPatchData?), string? name = default(string?), string? url = default(string?), string? description = default(string?), string? visibility = default(string?), System.IO.Stream? thumbnail = default(System.IO.Stream?), System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + + Org.OpenAPITools.Client.RequestOptions localVarRequestOptions = new Org.OpenAPITools.Client.RequestOptions(); + + string[] _contentTypes = new string[] { + "multipart/form-data" + }; + + // to determine the Accept header + string[] _accepts = new string[] { + "application/json" + }; + + + var localVarContentType = Org.OpenAPITools.Client.ClientUtils.SelectHeaderContentType(_contentTypes); + if (localVarContentType != null) localVarRequestOptions.HeaderParameters.Add("Content-Type", localVarContentType); + + var localVarAccept = Org.OpenAPITools.Client.ClientUtils.SelectHeaderAccept(_accepts); + if (localVarAccept != null) localVarRequestOptions.HeaderParameters.Add("Accept", localVarAccept); + + localVarRequestOptions.PathParameters.Add("asset", Org.OpenAPITools.Client.ClientUtils.ParameterToString(asset)); // path parameter + if (data != null) + { + localVarRequestOptions.FormParameters.Add("data", Org.OpenAPITools.Client.ClientUtils.ParameterToString(data)); // form parameter + } + if (name != null) + { + localVarRequestOptions.FormParameters.Add("name", Org.OpenAPITools.Client.ClientUtils.ParameterToString(name)); // form parameter + } + if (url != null) + { + localVarRequestOptions.FormParameters.Add("url", Org.OpenAPITools.Client.ClientUtils.ParameterToString(url)); // form parameter + } + if (description != null) + { + localVarRequestOptions.FormParameters.Add("description", Org.OpenAPITools.Client.ClientUtils.ParameterToString(description)); // form parameter + } + if (visibility != null) + { + localVarRequestOptions.FormParameters.Add("visibility", Org.OpenAPITools.Client.ClientUtils.ParameterToString(visibility)); // form parameter + } + if (thumbnail != null) + { + } + + // authentication (OAuth2PasswordBearer) required + // oauth required + if (!string.IsNullOrEmpty(this.Configuration.AccessToken) && !localVarRequestOptions.HeaderParameters.ContainsKey("Authorization")) + { + localVarRequestOptions.HeaderParameters.Add("Authorization", "Bearer " + this.Configuration.AccessToken); + } + + // make the HTTP request + + var task = this.AsynchronousClient.PatchAsync("/assets/{asset}", localVarRequestOptions, this.Configuration, cancellationToken); + +#if UNITY_EDITOR || !UNITY_WEBGL + var localVarResponse = await task.ConfigureAwait(false); +#else + var localVarResponse = await task; +#endif + + if (this.ExceptionFactory != null) + { + Exception _exception = this.ExceptionFactory("UpdateAssetAssetsAssetPatch", localVarResponse); + if (_exception != null) throw _exception; + } + + return localVarResponse; + } + + /// + /// Upload New Assets + /// + /// Thrown when fails to make API call + /// + /// Object + public Object UploadNewAssetsAssetsPost(List files) + { + Org.OpenAPITools.Client.ApiResponse localVarResponse = UploadNewAssetsAssetsPostWithHttpInfo(files); + return localVarResponse.Data; + } + + /// + /// Upload New Assets + /// + /// Thrown when fails to make API call + /// + /// ApiResponse of Object + public Org.OpenAPITools.Client.ApiResponse UploadNewAssetsAssetsPostWithHttpInfo(List files) + { + // verify the required parameter 'files' is set + if (files == null) + throw new Org.OpenAPITools.Client.ApiException(400, "Missing required parameter 'files' when calling AssetsApi->UploadNewAssetsAssetsPost"); + + Org.OpenAPITools.Client.RequestOptions localVarRequestOptions = new Org.OpenAPITools.Client.RequestOptions(); + + string[] _contentTypes = new string[] { + "multipart/form-data" + }; + + // to determine the Accept header + string[] _accepts = new string[] { + "application/json" + }; + + var localVarContentType = Org.OpenAPITools.Client.ClientUtils.SelectHeaderContentType(_contentTypes); + if (localVarContentType != null) localVarRequestOptions.HeaderParameters.Add("Content-Type", localVarContentType); + + var localVarAccept = Org.OpenAPITools.Client.ClientUtils.SelectHeaderAccept(_accepts); + if (localVarAccept != null) localVarRequestOptions.HeaderParameters.Add("Accept", localVarAccept); + + + // authentication (OAuth2PasswordBearer) required + // oauth required + if (!string.IsNullOrEmpty(this.Configuration.AccessToken) && !localVarRequestOptions.HeaderParameters.ContainsKey("Authorization")) + { + localVarRequestOptions.HeaderParameters.Add("Authorization", "Bearer " + this.Configuration.AccessToken); + } + + // make the HTTP request + var localVarResponse = this.Client.Post("/assets", localVarRequestOptions, this.Configuration); + + if (this.ExceptionFactory != null) + { + Exception _exception = this.ExceptionFactory("UploadNewAssetsAssetsPost", localVarResponse); + if (_exception != null) throw _exception; + } + + return localVarResponse; + } + + /// + /// Upload New Assets + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of Object + public async System.Threading.Tasks.Task UploadNewAssetsAssetsPostAsync(List files, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + var task = UploadNewAssetsAssetsPostWithHttpInfoAsync(files, cancellationToken); +#if UNITY_EDITOR || !UNITY_WEBGL + Org.OpenAPITools.Client.ApiResponse localVarResponse = await task.ConfigureAwait(false); +#else + Org.OpenAPITools.Client.ApiResponse localVarResponse = await task; +#endif + return localVarResponse.Data; + } + + /// + /// Upload New Assets + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of ApiResponse (Object) + public async System.Threading.Tasks.Task> UploadNewAssetsAssetsPostWithHttpInfoAsync(List files, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + // verify the required parameter 'files' is set + if (files == null) + throw new Org.OpenAPITools.Client.ApiException(400, "Missing required parameter 'files' when calling AssetsApi->UploadNewAssetsAssetsPost"); + + + Org.OpenAPITools.Client.RequestOptions localVarRequestOptions = new Org.OpenAPITools.Client.RequestOptions(); + + string[] _contentTypes = new string[] { + "multipart/form-data" + }; + + // to determine the Accept header + string[] _accepts = new string[] { + "application/json" + }; + + + var localVarContentType = Org.OpenAPITools.Client.ClientUtils.SelectHeaderContentType(_contentTypes); + if (localVarContentType != null) localVarRequestOptions.HeaderParameters.Add("Content-Type", localVarContentType); + + var localVarAccept = Org.OpenAPITools.Client.ClientUtils.SelectHeaderAccept(_accepts); + if (localVarAccept != null) localVarRequestOptions.HeaderParameters.Add("Accept", localVarAccept); + + + // authentication (OAuth2PasswordBearer) required + // oauth required + if (!string.IsNullOrEmpty(this.Configuration.AccessToken) && !localVarRequestOptions.HeaderParameters.ContainsKey("Authorization")) + { + localVarRequestOptions.HeaderParameters.Add("Authorization", "Bearer " + this.Configuration.AccessToken); + } + + // make the HTTP request + + var task = this.AsynchronousClient.PostAsync("/assets", localVarRequestOptions, this.Configuration, cancellationToken); + +#if UNITY_EDITOR || !UNITY_WEBGL + var localVarResponse = await task.ConfigureAwait(false); +#else + var localVarResponse = await task; +#endif + + if (this.ExceptionFactory != null) + { + Exception _exception = this.ExceptionFactory("UploadNewAssetsAssetsPost", localVarResponse); + if (_exception != null) throw _exception; + } + + return localVarResponse; + } + + } +} diff --git a/Assets/ThirdParty/Org.OpenAPITools/Api/AssetsApi.cs.meta b/Assets/ThirdParty/Org.OpenAPITools/Api/AssetsApi.cs.meta new file mode 100644 index 0000000000..b702a67c91 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Api/AssetsApi.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 83932cc0b007b4808be39d3abb684964 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThirdParty/Org.OpenAPITools/Api/LoginApi.cs b/Assets/ThirdParty/Org.OpenAPITools/Api/LoginApi.cs new file mode 100644 index 0000000000..4e56b143ea --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Api/LoginApi.cs @@ -0,0 +1,613 @@ +/* + * Icosa API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 0.1.0 + * Generated by: https://github.com/openapitools/openapi-generator.git + */ + + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Net; +using System.Net.Mime; +using Org.OpenAPITools.Client; +using Org.OpenAPITools.Model; + +namespace Org.OpenAPITools.Api +{ + + /// + /// Represents a collection of functions to interact with the API endpoints + /// + public interface ILoginApiSync : IApiAccessor + { + #region Synchronous Operations + /// + /// Device Login + /// + /// Thrown when fails to make API call + /// + /// LoginToken + LoginToken DeviceLoginLoginDeviceLoginPost(string deviceCode); + + /// + /// Device Login + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// ApiResponse of LoginToken + ApiResponse DeviceLoginLoginDeviceLoginPostWithHttpInfo(string deviceCode); + /// + /// Login + /// + /// Thrown when fails to make API call + /// + /// + /// (optional) + /// (optional, default to "") + /// (optional) + /// (optional) + /// LoginToken + LoginToken LoginLoginPost(string username, string password, string? grantType = default(string?), string? scope = default(string?), string? clientId = default(string?), string? clientSecret = default(string?)); + + /// + /// Login + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// + /// (optional) + /// (optional, default to "") + /// (optional) + /// (optional) + /// ApiResponse of LoginToken + ApiResponse LoginLoginPostWithHttpInfo(string username, string password, string? grantType = default(string?), string? scope = default(string?), string? clientId = default(string?), string? clientSecret = default(string?)); + #endregion Synchronous Operations + } + + /// + /// Represents a collection of functions to interact with the API endpoints + /// + public interface ILoginApiAsync : IApiAccessor + { + #region Asynchronous Operations + /// + /// Device Login + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of LoginToken + System.Threading.Tasks.Task DeviceLoginLoginDeviceLoginPostAsync(string deviceCode, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + + /// + /// Device Login + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of ApiResponse (LoginToken) + System.Threading.Tasks.Task> DeviceLoginLoginDeviceLoginPostWithHttpInfoAsync(string deviceCode, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + /// + /// Login + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// + /// (optional) + /// (optional, default to "") + /// (optional) + /// (optional) + /// Cancellation Token to cancel the request. + /// Task of LoginToken + System.Threading.Tasks.Task LoginLoginPostAsync(string username, string password, string? grantType = default(string?), string? scope = default(string?), string? clientId = default(string?), string? clientSecret = default(string?), System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + + /// + /// Login + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// + /// (optional) + /// (optional, default to "") + /// (optional) + /// (optional) + /// Cancellation Token to cancel the request. + /// Task of ApiResponse (LoginToken) + System.Threading.Tasks.Task> LoginLoginPostWithHttpInfoAsync(string username, string password, string? grantType = default(string?), string? scope = default(string?), string? clientId = default(string?), string? clientSecret = default(string?), System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + #endregion Asynchronous Operations + } + + /// + /// Represents a collection of functions to interact with the API endpoints + /// + public interface ILoginApi : ILoginApiSync, ILoginApiAsync + { + + } + + /// + /// Represents a collection of functions to interact with the API endpoints + /// + public partial class LoginApi : IDisposable, ILoginApi + { + private Org.OpenAPITools.Client.ExceptionFactory _exceptionFactory = (name, response) => null; + + /// + /// Initializes a new instance of the class. + /// **IMPORTANT** This will also create an instance of HttpClient, which is less than ideal. + /// It's better to reuse the HttpClient and HttpClientHandler. + /// + /// + public LoginApi() : this((string)null) + { + } + + /// + /// Initializes a new instance of the class. + /// **IMPORTANT** This will also create an instance of HttpClient, which is less than ideal. + /// It's better to reuse the HttpClient and HttpClientHandler. + /// + /// The target service's base path in URL format. + /// + /// + public LoginApi(string basePath) + { + this.Configuration = Org.OpenAPITools.Client.Configuration.MergeConfigurations( + Org.OpenAPITools.Client.GlobalConfiguration.Instance, + new Org.OpenAPITools.Client.Configuration { BasePath = basePath } + ); + this.ApiClient = new Org.OpenAPITools.Client.ApiClient(this.Configuration.BasePath); + this.Client = this.ApiClient; + this.AsynchronousClient = this.ApiClient; + this.ExceptionFactory = Org.OpenAPITools.Client.Configuration.DefaultExceptionFactory; + } + + /// + /// Initializes a new instance of the class using Configuration object. + /// **IMPORTANT** This will also create an instance of HttpClient, which is less than ideal. + /// It's better to reuse the HttpClient and HttpClientHandler. + /// + /// An instance of Configuration. + /// + /// + public LoginApi(Org.OpenAPITools.Client.Configuration configuration) + { + if (configuration == null) throw new ArgumentNullException("configuration"); + + this.Configuration = Org.OpenAPITools.Client.Configuration.MergeConfigurations( + Org.OpenAPITools.Client.GlobalConfiguration.Instance, + configuration + ); + this.ApiClient = new Org.OpenAPITools.Client.ApiClient(this.Configuration.BasePath); + this.Client = this.ApiClient; + this.AsynchronousClient = this.ApiClient; + ExceptionFactory = Org.OpenAPITools.Client.Configuration.DefaultExceptionFactory; + } + + /// + /// Initializes a new instance of the class + /// using a Configuration object and client instance. + /// + /// The client interface for synchronous API access. + /// The client interface for asynchronous API access. + /// The configuration object. + /// + public LoginApi(Org.OpenAPITools.Client.ISynchronousClient client, Org.OpenAPITools.Client.IAsynchronousClient asyncClient, Org.OpenAPITools.Client.IReadableConfiguration configuration) + { + if (client == null) throw new ArgumentNullException("client"); + if (asyncClient == null) throw new ArgumentNullException("asyncClient"); + if (configuration == null) throw new ArgumentNullException("configuration"); + + this.Client = client; + this.AsynchronousClient = asyncClient; + this.Configuration = configuration; + this.ExceptionFactory = Org.OpenAPITools.Client.Configuration.DefaultExceptionFactory; + } + + /// + /// Disposes resources if they were created by us + /// + public void Dispose() + { + this.ApiClient?.Dispose(); + } + + /// + /// Holds the ApiClient if created + /// + public Org.OpenAPITools.Client.ApiClient ApiClient { get; set; } = null; + + /// + /// The client for accessing this underlying API asynchronously. + /// + public Org.OpenAPITools.Client.IAsynchronousClient AsynchronousClient { get; set; } + + /// + /// The client for accessing this underlying API synchronously. + /// + public Org.OpenAPITools.Client.ISynchronousClient Client { get; set; } + + /// + /// Gets the base path of the API client. + /// + /// The base path + public string GetBasePath() + { + return this.Configuration.BasePath; + } + + /// + /// Gets or sets the configuration object + /// + /// An instance of the Configuration + public Org.OpenAPITools.Client.IReadableConfiguration Configuration { get; set; } + + /// + /// Provides a factory method hook for the creation of exceptions. + /// + public Org.OpenAPITools.Client.ExceptionFactory ExceptionFactory + { + get + { + if (_exceptionFactory != null && _exceptionFactory.GetInvocationList().Length > 1) + { + throw new InvalidOperationException("Multicast delegate for ExceptionFactory is unsupported."); + } + return _exceptionFactory; + } + set { _exceptionFactory = value; } + } + + /// + /// Device Login + /// + /// Thrown when fails to make API call + /// + /// LoginToken + public LoginToken DeviceLoginLoginDeviceLoginPost(string deviceCode) + { + Org.OpenAPITools.Client.ApiResponse localVarResponse = DeviceLoginLoginDeviceLoginPostWithHttpInfo(deviceCode); + return localVarResponse.Data; + } + + /// + /// Device Login + /// + /// Thrown when fails to make API call + /// + /// ApiResponse of LoginToken + public Org.OpenAPITools.Client.ApiResponse DeviceLoginLoginDeviceLoginPostWithHttpInfo(string deviceCode) + { + // verify the required parameter 'deviceCode' is set + if (deviceCode == null) + throw new Org.OpenAPITools.Client.ApiException(400, "Missing required parameter 'deviceCode' when calling LoginApi->DeviceLoginLoginDeviceLoginPost"); + + Org.OpenAPITools.Client.RequestOptions localVarRequestOptions = new Org.OpenAPITools.Client.RequestOptions(); + + string[] _contentTypes = new string[] { + }; + + // to determine the Accept header + string[] _accepts = new string[] { + "application/json" + }; + + var localVarContentType = Org.OpenAPITools.Client.ClientUtils.SelectHeaderContentType(_contentTypes); + if (localVarContentType != null) localVarRequestOptions.HeaderParameters.Add("Content-Type", localVarContentType); + + var localVarAccept = Org.OpenAPITools.Client.ClientUtils.SelectHeaderAccept(_accepts); + if (localVarAccept != null) localVarRequestOptions.HeaderParameters.Add("Accept", localVarAccept); + + localVarRequestOptions.QueryParameters.Add(Org.OpenAPITools.Client.ClientUtils.ParameterToMultiMap("", "device_code", deviceCode)); + + // authentication (OAuth2PasswordBearer) required + // oauth required + if (!string.IsNullOrEmpty(this.Configuration.AccessToken) && !localVarRequestOptions.HeaderParameters.ContainsKey("Authorization")) + { + localVarRequestOptions.HeaderParameters.Add("Authorization", "Bearer " + this.Configuration.AccessToken); + } + + // make the HTTP request + var localVarResponse = this.Client.Post("/login/device_login", localVarRequestOptions, this.Configuration); + + if (this.ExceptionFactory != null) + { + Exception _exception = this.ExceptionFactory("DeviceLoginLoginDeviceLoginPost", localVarResponse); + if (_exception != null) throw _exception; + } + + return localVarResponse; + } + + /// + /// Device Login + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of LoginToken + public async System.Threading.Tasks.Task DeviceLoginLoginDeviceLoginPostAsync(string deviceCode, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + var task = DeviceLoginLoginDeviceLoginPostWithHttpInfoAsync(deviceCode, cancellationToken); +#if UNITY_EDITOR || !UNITY_WEBGL + Org.OpenAPITools.Client.ApiResponse localVarResponse = await task.ConfigureAwait(false); +#else + Org.OpenAPITools.Client.ApiResponse localVarResponse = await task; +#endif + return localVarResponse.Data; + } + + /// + /// Device Login + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of ApiResponse (LoginToken) + public async System.Threading.Tasks.Task> DeviceLoginLoginDeviceLoginPostWithHttpInfoAsync(string deviceCode, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + // verify the required parameter 'deviceCode' is set + if (deviceCode == null) + throw new Org.OpenAPITools.Client.ApiException(400, "Missing required parameter 'deviceCode' when calling LoginApi->DeviceLoginLoginDeviceLoginPost"); + + + Org.OpenAPITools.Client.RequestOptions localVarRequestOptions = new Org.OpenAPITools.Client.RequestOptions(); + + string[] _contentTypes = new string[] { + }; + + // to determine the Accept header + string[] _accepts = new string[] { + "application/json" + }; + + + var localVarContentType = Org.OpenAPITools.Client.ClientUtils.SelectHeaderContentType(_contentTypes); + if (localVarContentType != null) localVarRequestOptions.HeaderParameters.Add("Content-Type", localVarContentType); + + var localVarAccept = Org.OpenAPITools.Client.ClientUtils.SelectHeaderAccept(_accepts); + if (localVarAccept != null) localVarRequestOptions.HeaderParameters.Add("Accept", localVarAccept); + + localVarRequestOptions.QueryParameters.Add(Org.OpenAPITools.Client.ClientUtils.ParameterToMultiMap("", "device_code", deviceCode)); + + // authentication (OAuth2PasswordBearer) required + // oauth required + if (!string.IsNullOrEmpty(this.Configuration.AccessToken) && !localVarRequestOptions.HeaderParameters.ContainsKey("Authorization")) + { + localVarRequestOptions.HeaderParameters.Add("Authorization", "Bearer " + this.Configuration.AccessToken); + } + + // make the HTTP request + + var task = this.AsynchronousClient.PostAsync("/login/device_login", localVarRequestOptions, this.Configuration, cancellationToken); + +#if UNITY_EDITOR || !UNITY_WEBGL + var localVarResponse = await task.ConfigureAwait(false); +#else + var localVarResponse = await task; +#endif + + if (this.ExceptionFactory != null) + { + Exception _exception = this.ExceptionFactory("DeviceLoginLoginDeviceLoginPost", localVarResponse); + if (_exception != null) throw _exception; + } + + return localVarResponse; + } + + /// + /// Login + /// + /// Thrown when fails to make API call + /// + /// + /// (optional) + /// (optional, default to "") + /// (optional) + /// (optional) + /// LoginToken + public LoginToken LoginLoginPost(string username, string password, string? grantType = default(string?), string? scope = default(string?), string? clientId = default(string?), string? clientSecret = default(string?)) + { + Org.OpenAPITools.Client.ApiResponse localVarResponse = LoginLoginPostWithHttpInfo(username, password, grantType, scope, clientId, clientSecret); + return localVarResponse.Data; + } + + /// + /// Login + /// + /// Thrown when fails to make API call + /// + /// + /// (optional) + /// (optional, default to "") + /// (optional) + /// (optional) + /// ApiResponse of LoginToken + public Org.OpenAPITools.Client.ApiResponse LoginLoginPostWithHttpInfo(string username, string password, string? grantType = default(string?), string? scope = default(string?), string? clientId = default(string?), string? clientSecret = default(string?)) + { + // verify the required parameter 'username' is set + if (username == null) + throw new Org.OpenAPITools.Client.ApiException(400, "Missing required parameter 'username' when calling LoginApi->LoginLoginPost"); + + // verify the required parameter 'password' is set + if (password == null) + throw new Org.OpenAPITools.Client.ApiException(400, "Missing required parameter 'password' when calling LoginApi->LoginLoginPost"); + + Org.OpenAPITools.Client.RequestOptions localVarRequestOptions = new Org.OpenAPITools.Client.RequestOptions(); + + string[] _contentTypes = new string[] { + "application/x-www-form-urlencoded" + }; + + // to determine the Accept header + string[] _accepts = new string[] { + "application/json" + }; + + var localVarContentType = Org.OpenAPITools.Client.ClientUtils.SelectHeaderContentType(_contentTypes); + if (localVarContentType != null) localVarRequestOptions.HeaderParameters.Add("Content-Type", localVarContentType); + + var localVarAccept = Org.OpenAPITools.Client.ClientUtils.SelectHeaderAccept(_accepts); + if (localVarAccept != null) localVarRequestOptions.HeaderParameters.Add("Accept", localVarAccept); + + if (grantType != null) + { + localVarRequestOptions.FormParameters.Add("grant_type", Org.OpenAPITools.Client.ClientUtils.ParameterToString(grantType)); // form parameter + } + localVarRequestOptions.FormParameters.Add("username", Org.OpenAPITools.Client.ClientUtils.ParameterToString(username)); // form parameter + localVarRequestOptions.FormParameters.Add("password", Org.OpenAPITools.Client.ClientUtils.ParameterToString(password)); // form parameter + if (scope != null) + { + localVarRequestOptions.FormParameters.Add("scope", Org.OpenAPITools.Client.ClientUtils.ParameterToString(scope)); // form parameter + } + if (clientId != null) + { + localVarRequestOptions.FormParameters.Add("client_id", Org.OpenAPITools.Client.ClientUtils.ParameterToString(clientId)); // form parameter + } + if (clientSecret != null) + { + localVarRequestOptions.FormParameters.Add("client_secret", Org.OpenAPITools.Client.ClientUtils.ParameterToString(clientSecret)); // form parameter + } + + + // make the HTTP request + var localVarResponse = this.Client.Post("/login", localVarRequestOptions, this.Configuration); + + if (this.ExceptionFactory != null) + { + Exception _exception = this.ExceptionFactory("LoginLoginPost", localVarResponse); + if (_exception != null) throw _exception; + } + + return localVarResponse; + } + + /// + /// Login + /// + /// Thrown when fails to make API call + /// + /// + /// (optional) + /// (optional, default to "") + /// (optional) + /// (optional) + /// Cancellation Token to cancel the request. + /// Task of LoginToken + public async System.Threading.Tasks.Task LoginLoginPostAsync(string username, string password, string? grantType = default(string?), string? scope = default(string?), string? clientId = default(string?), string? clientSecret = default(string?), System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + var task = LoginLoginPostWithHttpInfoAsync(username, password, grantType, scope, clientId, clientSecret, cancellationToken); +#if UNITY_EDITOR || !UNITY_WEBGL + Org.OpenAPITools.Client.ApiResponse localVarResponse = await task.ConfigureAwait(false); +#else + Org.OpenAPITools.Client.ApiResponse localVarResponse = await task; +#endif + return localVarResponse.Data; + } + + /// + /// Login + /// + /// Thrown when fails to make API call + /// + /// + /// (optional) + /// (optional, default to "") + /// (optional) + /// (optional) + /// Cancellation Token to cancel the request. + /// Task of ApiResponse (LoginToken) + public async System.Threading.Tasks.Task> LoginLoginPostWithHttpInfoAsync(string username, string password, string? grantType = default(string?), string? scope = default(string?), string? clientId = default(string?), string? clientSecret = default(string?), System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + // verify the required parameter 'username' is set + if (username == null) + throw new Org.OpenAPITools.Client.ApiException(400, "Missing required parameter 'username' when calling LoginApi->LoginLoginPost"); + + // verify the required parameter 'password' is set + if (password == null) + throw new Org.OpenAPITools.Client.ApiException(400, "Missing required parameter 'password' when calling LoginApi->LoginLoginPost"); + + + Org.OpenAPITools.Client.RequestOptions localVarRequestOptions = new Org.OpenAPITools.Client.RequestOptions(); + + string[] _contentTypes = new string[] { + "application/x-www-form-urlencoded" + }; + + // to determine the Accept header + string[] _accepts = new string[] { + "application/json" + }; + + + var localVarContentType = Org.OpenAPITools.Client.ClientUtils.SelectHeaderContentType(_contentTypes); + if (localVarContentType != null) localVarRequestOptions.HeaderParameters.Add("Content-Type", localVarContentType); + + var localVarAccept = Org.OpenAPITools.Client.ClientUtils.SelectHeaderAccept(_accepts); + if (localVarAccept != null) localVarRequestOptions.HeaderParameters.Add("Accept", localVarAccept); + + if (grantType != null) + { + localVarRequestOptions.FormParameters.Add("grant_type", Org.OpenAPITools.Client.ClientUtils.ParameterToString(grantType)); // form parameter + } + localVarRequestOptions.FormParameters.Add("username", Org.OpenAPITools.Client.ClientUtils.ParameterToString(username)); // form parameter + localVarRequestOptions.FormParameters.Add("password", Org.OpenAPITools.Client.ClientUtils.ParameterToString(password)); // form parameter + if (scope != null) + { + localVarRequestOptions.FormParameters.Add("scope", Org.OpenAPITools.Client.ClientUtils.ParameterToString(scope)); // form parameter + } + if (clientId != null) + { + localVarRequestOptions.FormParameters.Add("client_id", Org.OpenAPITools.Client.ClientUtils.ParameterToString(clientId)); // form parameter + } + if (clientSecret != null) + { + localVarRequestOptions.FormParameters.Add("client_secret", Org.OpenAPITools.Client.ClientUtils.ParameterToString(clientSecret)); // form parameter + } + + + // make the HTTP request + + var task = this.AsynchronousClient.PostAsync("/login", localVarRequestOptions, this.Configuration, cancellationToken); + +#if UNITY_EDITOR || !UNITY_WEBGL + var localVarResponse = await task.ConfigureAwait(false); +#else + var localVarResponse = await task; +#endif + + if (this.ExceptionFactory != null) + { + Exception _exception = this.ExceptionFactory("LoginLoginPost", localVarResponse); + if (_exception != null) throw _exception; + } + + return localVarResponse; + } + + } +} diff --git a/Assets/ThirdParty/Org.OpenAPITools/Api/LoginApi.cs.meta b/Assets/ThirdParty/Org.OpenAPITools/Api/LoginApi.cs.meta new file mode 100644 index 0000000000..497467a841 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Api/LoginApi.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d534d3cdaa5ca4751a0619feb7d7828b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThirdParty/Org.OpenAPITools/Api/PolyApi.cs b/Assets/ThirdParty/Org.OpenAPITools/Api/PolyApi.cs new file mode 100644 index 0000000000..e51dada320 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Api/PolyApi.cs @@ -0,0 +1,728 @@ +/* + * Icosa API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 0.1.0 + * Generated by: https://github.com/openapitools/openapi-generator.git + */ + + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Net; +using System.Net.Mime; +using Org.OpenAPITools.Client; +using Org.OpenAPITools.Model; + +namespace Org.OpenAPITools.Api +{ + + /// + /// Represents a collection of functions to interact with the API endpoints + /// + public interface IPolyApiSync : IApiAccessor + { + #region Synchronous Operations + /// + /// Get Poly Asset + /// + /// Thrown when fails to make API call + /// + /// PolyAsset + PolyAsset GetPolyAssetPolyAssetsAssetGet(string asset); + + /// + /// Get Poly Asset + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// ApiResponse of PolyAsset + ApiResponse GetPolyAssetPolyAssetsAssetGetWithHttpInfo(string asset); + /// + /// Get Poly Assets List + /// + /// Thrown when fails to make API call + /// (optional, default to 20) + /// (optional, default to 0) + /// (optional, default to false) + /// PolyList + PolyList GetPolyAssetsListPolyAssetsGet(int? results = default(int?), int? page = default(int?), bool? curated = default(bool?)); + + /// + /// Get Poly Assets List + /// + /// + /// + /// + /// Thrown when fails to make API call + /// (optional, default to 20) + /// (optional, default to 0) + /// (optional, default to false) + /// ApiResponse of PolyList + ApiResponse GetPolyAssetsListPolyAssetsGetWithHttpInfo(int? results = default(int?), int? page = default(int?), bool? curated = default(bool?)); + /// + /// Import Poly Data + /// + /// Thrown when fails to make API call + /// + /// Object + Object ImportPolyDataPolyImportPost(List requestBody); + + /// + /// Import Poly Data + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// ApiResponse of Object + ApiResponse ImportPolyDataPolyImportPostWithHttpInfo(List requestBody); + #endregion Synchronous Operations + } + + /// + /// Represents a collection of functions to interact with the API endpoints + /// + public interface IPolyApiAsync : IApiAccessor + { + #region Asynchronous Operations + /// + /// Get Poly Asset + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of PolyAsset + System.Threading.Tasks.Task GetPolyAssetPolyAssetsAssetGetAsync(string asset, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + + /// + /// Get Poly Asset + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of ApiResponse (PolyAsset) + System.Threading.Tasks.Task> GetPolyAssetPolyAssetsAssetGetWithHttpInfoAsync(string asset, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + /// + /// Get Poly Assets List + /// + /// + /// + /// + /// Thrown when fails to make API call + /// (optional, default to 20) + /// (optional, default to 0) + /// (optional, default to false) + /// Cancellation Token to cancel the request. + /// Task of PolyList + System.Threading.Tasks.Task GetPolyAssetsListPolyAssetsGetAsync(int? results = default(int?), int? page = default(int?), bool? curated = default(bool?), System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + + /// + /// Get Poly Assets List + /// + /// + /// + /// + /// Thrown when fails to make API call + /// (optional, default to 20) + /// (optional, default to 0) + /// (optional, default to false) + /// Cancellation Token to cancel the request. + /// Task of ApiResponse (PolyList) + System.Threading.Tasks.Task> GetPolyAssetsListPolyAssetsGetWithHttpInfoAsync(int? results = default(int?), int? page = default(int?), bool? curated = default(bool?), System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + /// + /// Import Poly Data + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of Object + System.Threading.Tasks.Task ImportPolyDataPolyImportPostAsync(List requestBody, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + + /// + /// Import Poly Data + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of ApiResponse (Object) + System.Threading.Tasks.Task> ImportPolyDataPolyImportPostWithHttpInfoAsync(List requestBody, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + #endregion Asynchronous Operations + } + + /// + /// Represents a collection of functions to interact with the API endpoints + /// + public interface IPolyApi : IPolyApiSync, IPolyApiAsync + { + + } + + /// + /// Represents a collection of functions to interact with the API endpoints + /// + public partial class PolyApi : IDisposable, IPolyApi + { + private Org.OpenAPITools.Client.ExceptionFactory _exceptionFactory = (name, response) => null; + + /// + /// Initializes a new instance of the class. + /// **IMPORTANT** This will also create an instance of HttpClient, which is less than ideal. + /// It's better to reuse the HttpClient and HttpClientHandler. + /// + /// + public PolyApi() : this((string)null) + { + } + + /// + /// Initializes a new instance of the class. + /// **IMPORTANT** This will also create an instance of HttpClient, which is less than ideal. + /// It's better to reuse the HttpClient and HttpClientHandler. + /// + /// The target service's base path in URL format. + /// + /// + public PolyApi(string basePath) + { + this.Configuration = Org.OpenAPITools.Client.Configuration.MergeConfigurations( + Org.OpenAPITools.Client.GlobalConfiguration.Instance, + new Org.OpenAPITools.Client.Configuration { BasePath = basePath } + ); + this.ApiClient = new Org.OpenAPITools.Client.ApiClient(this.Configuration.BasePath); + this.Client = this.ApiClient; + this.AsynchronousClient = this.ApiClient; + this.ExceptionFactory = Org.OpenAPITools.Client.Configuration.DefaultExceptionFactory; + } + + /// + /// Initializes a new instance of the class using Configuration object. + /// **IMPORTANT** This will also create an instance of HttpClient, which is less than ideal. + /// It's better to reuse the HttpClient and HttpClientHandler. + /// + /// An instance of Configuration. + /// + /// + public PolyApi(Org.OpenAPITools.Client.Configuration configuration) + { + if (configuration == null) throw new ArgumentNullException("configuration"); + + this.Configuration = Org.OpenAPITools.Client.Configuration.MergeConfigurations( + Org.OpenAPITools.Client.GlobalConfiguration.Instance, + configuration + ); + this.ApiClient = new Org.OpenAPITools.Client.ApiClient(this.Configuration.BasePath); + this.Client = this.ApiClient; + this.AsynchronousClient = this.ApiClient; + ExceptionFactory = Org.OpenAPITools.Client.Configuration.DefaultExceptionFactory; + } + + /// + /// Initializes a new instance of the class + /// using a Configuration object and client instance. + /// + /// The client interface for synchronous API access. + /// The client interface for asynchronous API access. + /// The configuration object. + /// + public PolyApi(Org.OpenAPITools.Client.ISynchronousClient client, Org.OpenAPITools.Client.IAsynchronousClient asyncClient, Org.OpenAPITools.Client.IReadableConfiguration configuration) + { + if (client == null) throw new ArgumentNullException("client"); + if (asyncClient == null) throw new ArgumentNullException("asyncClient"); + if (configuration == null) throw new ArgumentNullException("configuration"); + + this.Client = client; + this.AsynchronousClient = asyncClient; + this.Configuration = configuration; + this.ExceptionFactory = Org.OpenAPITools.Client.Configuration.DefaultExceptionFactory; + } + + /// + /// Disposes resources if they were created by us + /// + public void Dispose() + { + this.ApiClient?.Dispose(); + } + + /// + /// Holds the ApiClient if created + /// + public Org.OpenAPITools.Client.ApiClient ApiClient { get; set; } = null; + + /// + /// The client for accessing this underlying API asynchronously. + /// + public Org.OpenAPITools.Client.IAsynchronousClient AsynchronousClient { get; set; } + + /// + /// The client for accessing this underlying API synchronously. + /// + public Org.OpenAPITools.Client.ISynchronousClient Client { get; set; } + + /// + /// Gets the base path of the API client. + /// + /// The base path + public string GetBasePath() + { + return this.Configuration.BasePath; + } + + /// + /// Gets or sets the configuration object + /// + /// An instance of the Configuration + public Org.OpenAPITools.Client.IReadableConfiguration Configuration { get; set; } + + /// + /// Provides a factory method hook for the creation of exceptions. + /// + public Org.OpenAPITools.Client.ExceptionFactory ExceptionFactory + { + get + { + if (_exceptionFactory != null && _exceptionFactory.GetInvocationList().Length > 1) + { + throw new InvalidOperationException("Multicast delegate for ExceptionFactory is unsupported."); + } + return _exceptionFactory; + } + set { _exceptionFactory = value; } + } + + /// + /// Get Poly Asset + /// + /// Thrown when fails to make API call + /// + /// PolyAsset + public PolyAsset GetPolyAssetPolyAssetsAssetGet(string asset) + { + Org.OpenAPITools.Client.ApiResponse localVarResponse = GetPolyAssetPolyAssetsAssetGetWithHttpInfo(asset); + return localVarResponse.Data; + } + + /// + /// Get Poly Asset + /// + /// Thrown when fails to make API call + /// + /// ApiResponse of PolyAsset + public Org.OpenAPITools.Client.ApiResponse GetPolyAssetPolyAssetsAssetGetWithHttpInfo(string asset) + { + // verify the required parameter 'asset' is set + if (asset == null) + throw new Org.OpenAPITools.Client.ApiException(400, "Missing required parameter 'asset' when calling PolyApi->GetPolyAssetPolyAssetsAssetGet"); + + Org.OpenAPITools.Client.RequestOptions localVarRequestOptions = new Org.OpenAPITools.Client.RequestOptions(); + + string[] _contentTypes = new string[] { + }; + + // to determine the Accept header + string[] _accepts = new string[] { + "application/json" + }; + + var localVarContentType = Org.OpenAPITools.Client.ClientUtils.SelectHeaderContentType(_contentTypes); + if (localVarContentType != null) localVarRequestOptions.HeaderParameters.Add("Content-Type", localVarContentType); + + var localVarAccept = Org.OpenAPITools.Client.ClientUtils.SelectHeaderAccept(_accepts); + if (localVarAccept != null) localVarRequestOptions.HeaderParameters.Add("Accept", localVarAccept); + + localVarRequestOptions.PathParameters.Add("asset", Org.OpenAPITools.Client.ClientUtils.ParameterToString(asset)); // path parameter + + + // make the HTTP request + var localVarResponse = this.Client.Get("/poly/assets/{asset}", localVarRequestOptions, this.Configuration); + + if (this.ExceptionFactory != null) + { + Exception _exception = this.ExceptionFactory("GetPolyAssetPolyAssetsAssetGet", localVarResponse); + if (_exception != null) throw _exception; + } + + return localVarResponse; + } + + /// + /// Get Poly Asset + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of PolyAsset + public async System.Threading.Tasks.Task GetPolyAssetPolyAssetsAssetGetAsync(string asset, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + var task = GetPolyAssetPolyAssetsAssetGetWithHttpInfoAsync(asset, cancellationToken); +#if UNITY_EDITOR || !UNITY_WEBGL + Org.OpenAPITools.Client.ApiResponse localVarResponse = await task.ConfigureAwait(false); +#else + Org.OpenAPITools.Client.ApiResponse localVarResponse = await task; +#endif + return localVarResponse.Data; + } + + /// + /// Get Poly Asset + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of ApiResponse (PolyAsset) + public async System.Threading.Tasks.Task> GetPolyAssetPolyAssetsAssetGetWithHttpInfoAsync(string asset, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + // verify the required parameter 'asset' is set + if (asset == null) + throw new Org.OpenAPITools.Client.ApiException(400, "Missing required parameter 'asset' when calling PolyApi->GetPolyAssetPolyAssetsAssetGet"); + + + Org.OpenAPITools.Client.RequestOptions localVarRequestOptions = new Org.OpenAPITools.Client.RequestOptions(); + + string[] _contentTypes = new string[] { + }; + + // to determine the Accept header + string[] _accepts = new string[] { + "application/json" + }; + + + var localVarContentType = Org.OpenAPITools.Client.ClientUtils.SelectHeaderContentType(_contentTypes); + if (localVarContentType != null) localVarRequestOptions.HeaderParameters.Add("Content-Type", localVarContentType); + + var localVarAccept = Org.OpenAPITools.Client.ClientUtils.SelectHeaderAccept(_accepts); + if (localVarAccept != null) localVarRequestOptions.HeaderParameters.Add("Accept", localVarAccept); + + localVarRequestOptions.PathParameters.Add("asset", Org.OpenAPITools.Client.ClientUtils.ParameterToString(asset)); // path parameter + + + // make the HTTP request + + var task = this.AsynchronousClient.GetAsync("/poly/assets/{asset}", localVarRequestOptions, this.Configuration, cancellationToken); + +#if UNITY_EDITOR || !UNITY_WEBGL + var localVarResponse = await task.ConfigureAwait(false); +#else + var localVarResponse = await task; +#endif + + if (this.ExceptionFactory != null) + { + Exception _exception = this.ExceptionFactory("GetPolyAssetPolyAssetsAssetGet", localVarResponse); + if (_exception != null) throw _exception; + } + + return localVarResponse; + } + + /// + /// Get Poly Assets List + /// + /// Thrown when fails to make API call + /// (optional, default to 20) + /// (optional, default to 0) + /// (optional, default to false) + /// PolyList + public PolyList GetPolyAssetsListPolyAssetsGet(int? results = default(int?), int? page = default(int?), bool? curated = default(bool?)) + { + Org.OpenAPITools.Client.ApiResponse localVarResponse = GetPolyAssetsListPolyAssetsGetWithHttpInfo(results, page, curated); + return localVarResponse.Data; + } + + /// + /// Get Poly Assets List + /// + /// Thrown when fails to make API call + /// (optional, default to 20) + /// (optional, default to 0) + /// (optional, default to false) + /// ApiResponse of PolyList + public Org.OpenAPITools.Client.ApiResponse GetPolyAssetsListPolyAssetsGetWithHttpInfo(int? results = default(int?), int? page = default(int?), bool? curated = default(bool?)) + { + Org.OpenAPITools.Client.RequestOptions localVarRequestOptions = new Org.OpenAPITools.Client.RequestOptions(); + + string[] _contentTypes = new string[] { + }; + + // to determine the Accept header + string[] _accepts = new string[] { + "application/json" + }; + + var localVarContentType = Org.OpenAPITools.Client.ClientUtils.SelectHeaderContentType(_contentTypes); + if (localVarContentType != null) localVarRequestOptions.HeaderParameters.Add("Content-Type", localVarContentType); + + var localVarAccept = Org.OpenAPITools.Client.ClientUtils.SelectHeaderAccept(_accepts); + if (localVarAccept != null) localVarRequestOptions.HeaderParameters.Add("Accept", localVarAccept); + + if (results != null) + { + localVarRequestOptions.QueryParameters.Add(Org.OpenAPITools.Client.ClientUtils.ParameterToMultiMap("", "results", results)); + } + if (page != null) + { + localVarRequestOptions.QueryParameters.Add(Org.OpenAPITools.Client.ClientUtils.ParameterToMultiMap("", "page", page)); + } + if (curated != null) + { + localVarRequestOptions.QueryParameters.Add(Org.OpenAPITools.Client.ClientUtils.ParameterToMultiMap("", "curated", curated)); + } + + + // make the HTTP request + var localVarResponse = this.Client.Get("/poly/assets", localVarRequestOptions, this.Configuration); + + if (this.ExceptionFactory != null) + { + Exception _exception = this.ExceptionFactory("GetPolyAssetsListPolyAssetsGet", localVarResponse); + if (_exception != null) throw _exception; + } + + return localVarResponse; + } + + /// + /// Get Poly Assets List + /// + /// Thrown when fails to make API call + /// (optional, default to 20) + /// (optional, default to 0) + /// (optional, default to false) + /// Cancellation Token to cancel the request. + /// Task of PolyList + public async System.Threading.Tasks.Task GetPolyAssetsListPolyAssetsGetAsync(int? results = default(int?), int? page = default(int?), bool? curated = default(bool?), System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + var task = GetPolyAssetsListPolyAssetsGetWithHttpInfoAsync(results, page, curated, cancellationToken); +#if UNITY_EDITOR || !UNITY_WEBGL + Org.OpenAPITools.Client.ApiResponse localVarResponse = await task.ConfigureAwait(false); +#else + Org.OpenAPITools.Client.ApiResponse localVarResponse = await task; +#endif + return localVarResponse.Data; + } + + /// + /// Get Poly Assets List + /// + /// Thrown when fails to make API call + /// (optional, default to 20) + /// (optional, default to 0) + /// (optional, default to false) + /// Cancellation Token to cancel the request. + /// Task of ApiResponse (PolyList) + public async System.Threading.Tasks.Task> GetPolyAssetsListPolyAssetsGetWithHttpInfoAsync(int? results = default(int?), int? page = default(int?), bool? curated = default(bool?), System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + + Org.OpenAPITools.Client.RequestOptions localVarRequestOptions = new Org.OpenAPITools.Client.RequestOptions(); + + string[] _contentTypes = new string[] { + }; + + // to determine the Accept header + string[] _accepts = new string[] { + "application/json" + }; + + + var localVarContentType = Org.OpenAPITools.Client.ClientUtils.SelectHeaderContentType(_contentTypes); + if (localVarContentType != null) localVarRequestOptions.HeaderParameters.Add("Content-Type", localVarContentType); + + var localVarAccept = Org.OpenAPITools.Client.ClientUtils.SelectHeaderAccept(_accepts); + if (localVarAccept != null) localVarRequestOptions.HeaderParameters.Add("Accept", localVarAccept); + + if (results != null) + { + localVarRequestOptions.QueryParameters.Add(Org.OpenAPITools.Client.ClientUtils.ParameterToMultiMap("", "results", results)); + } + if (page != null) + { + localVarRequestOptions.QueryParameters.Add(Org.OpenAPITools.Client.ClientUtils.ParameterToMultiMap("", "page", page)); + } + if (curated != null) + { + localVarRequestOptions.QueryParameters.Add(Org.OpenAPITools.Client.ClientUtils.ParameterToMultiMap("", "curated", curated)); + } + + + // make the HTTP request + + var task = this.AsynchronousClient.GetAsync("/poly/assets", localVarRequestOptions, this.Configuration, cancellationToken); + +#if UNITY_EDITOR || !UNITY_WEBGL + var localVarResponse = await task.ConfigureAwait(false); +#else + var localVarResponse = await task; +#endif + + if (this.ExceptionFactory != null) + { + Exception _exception = this.ExceptionFactory("GetPolyAssetsListPolyAssetsGet", localVarResponse); + if (_exception != null) throw _exception; + } + + return localVarResponse; + } + + /// + /// Import Poly Data + /// + /// Thrown when fails to make API call + /// + /// Object + public Object ImportPolyDataPolyImportPost(List requestBody) + { + Org.OpenAPITools.Client.ApiResponse localVarResponse = ImportPolyDataPolyImportPostWithHttpInfo(requestBody); + return localVarResponse.Data; + } + + /// + /// Import Poly Data + /// + /// Thrown when fails to make API call + /// + /// ApiResponse of Object + public Org.OpenAPITools.Client.ApiResponse ImportPolyDataPolyImportPostWithHttpInfo(List requestBody) + { + // verify the required parameter 'requestBody' is set + if (requestBody == null) + throw new Org.OpenAPITools.Client.ApiException(400, "Missing required parameter 'requestBody' when calling PolyApi->ImportPolyDataPolyImportPost"); + + Org.OpenAPITools.Client.RequestOptions localVarRequestOptions = new Org.OpenAPITools.Client.RequestOptions(); + + string[] _contentTypes = new string[] { + "application/json" + }; + + // to determine the Accept header + string[] _accepts = new string[] { + "application/json" + }; + + var localVarContentType = Org.OpenAPITools.Client.ClientUtils.SelectHeaderContentType(_contentTypes); + if (localVarContentType != null) localVarRequestOptions.HeaderParameters.Add("Content-Type", localVarContentType); + + var localVarAccept = Org.OpenAPITools.Client.ClientUtils.SelectHeaderAccept(_accepts); + if (localVarAccept != null) localVarRequestOptions.HeaderParameters.Add("Accept", localVarAccept); + + localVarRequestOptions.Data = requestBody; + + // authentication (OAuth2PasswordBearer) required + // oauth required + if (!string.IsNullOrEmpty(this.Configuration.AccessToken) && !localVarRequestOptions.HeaderParameters.ContainsKey("Authorization")) + { + localVarRequestOptions.HeaderParameters.Add("Authorization", "Bearer " + this.Configuration.AccessToken); + } + + // make the HTTP request + var localVarResponse = this.Client.Post("/poly/import", localVarRequestOptions, this.Configuration); + + if (this.ExceptionFactory != null) + { + Exception _exception = this.ExceptionFactory("ImportPolyDataPolyImportPost", localVarResponse); + if (_exception != null) throw _exception; + } + + return localVarResponse; + } + + /// + /// Import Poly Data + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of Object + public async System.Threading.Tasks.Task ImportPolyDataPolyImportPostAsync(List requestBody, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + var task = ImportPolyDataPolyImportPostWithHttpInfoAsync(requestBody, cancellationToken); +#if UNITY_EDITOR || !UNITY_WEBGL + Org.OpenAPITools.Client.ApiResponse localVarResponse = await task.ConfigureAwait(false); +#else + Org.OpenAPITools.Client.ApiResponse localVarResponse = await task; +#endif + return localVarResponse.Data; + } + + /// + /// Import Poly Data + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of ApiResponse (Object) + public async System.Threading.Tasks.Task> ImportPolyDataPolyImportPostWithHttpInfoAsync(List requestBody, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + // verify the required parameter 'requestBody' is set + if (requestBody == null) + throw new Org.OpenAPITools.Client.ApiException(400, "Missing required parameter 'requestBody' when calling PolyApi->ImportPolyDataPolyImportPost"); + + + Org.OpenAPITools.Client.RequestOptions localVarRequestOptions = new Org.OpenAPITools.Client.RequestOptions(); + + string[] _contentTypes = new string[] { + "application/json" + }; + + // to determine the Accept header + string[] _accepts = new string[] { + "application/json" + }; + + + var localVarContentType = Org.OpenAPITools.Client.ClientUtils.SelectHeaderContentType(_contentTypes); + if (localVarContentType != null) localVarRequestOptions.HeaderParameters.Add("Content-Type", localVarContentType); + + var localVarAccept = Org.OpenAPITools.Client.ClientUtils.SelectHeaderAccept(_accepts); + if (localVarAccept != null) localVarRequestOptions.HeaderParameters.Add("Accept", localVarAccept); + + localVarRequestOptions.Data = requestBody; + + // authentication (OAuth2PasswordBearer) required + // oauth required + if (!string.IsNullOrEmpty(this.Configuration.AccessToken) && !localVarRequestOptions.HeaderParameters.ContainsKey("Authorization")) + { + localVarRequestOptions.HeaderParameters.Add("Authorization", "Bearer " + this.Configuration.AccessToken); + } + + // make the HTTP request + + var task = this.AsynchronousClient.PostAsync("/poly/import", localVarRequestOptions, this.Configuration, cancellationToken); + +#if UNITY_EDITOR || !UNITY_WEBGL + var localVarResponse = await task.ConfigureAwait(false); +#else + var localVarResponse = await task; +#endif + + if (this.ExceptionFactory != null) + { + Exception _exception = this.ExceptionFactory("ImportPolyDataPolyImportPost", localVarResponse); + if (_exception != null) throw _exception; + } + + return localVarResponse; + } + + } +} diff --git a/Assets/ThirdParty/Org.OpenAPITools/Api/PolyApi.cs.meta b/Assets/ThirdParty/Org.OpenAPITools/Api/PolyApi.cs.meta new file mode 100644 index 0000000000..51a541e655 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Api/PolyApi.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b7231a33deb094e41861d191e3b76693 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThirdParty/Org.OpenAPITools/Api/UsersApi.cs b/Assets/ThirdParty/Org.OpenAPITools/Api/UsersApi.cs new file mode 100644 index 0000000000..1ce7cacc50 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Api/UsersApi.cs @@ -0,0 +1,2392 @@ +/* + * Icosa API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 0.1.0 + * Generated by: https://github.com/openapitools/openapi-generator.git + */ + + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Net; +using System.Net.Mime; +using Org.OpenAPITools.Client; +using Org.OpenAPITools.Model; + +namespace Org.OpenAPITools.Api +{ + + /// + /// Represents a collection of functions to interact with the API endpoints + /// + public interface IUsersApiSync : IApiAccessor + { + #region Synchronous Operations + /// + /// Change Authenticated User Email + /// + /// Thrown when fails to make API call + /// + /// Object + Object ChangeAuthenticatedUserEmailUsersMeEmailPatch(EmailChangeAuthenticated emailChangeAuthenticated); + + /// + /// Change Authenticated User Email + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// ApiResponse of Object + ApiResponse ChangeAuthenticatedUserEmailUsersMeEmailPatchWithHttpInfo(EmailChangeAuthenticated emailChangeAuthenticated); + /// + /// Change Authenticated User Password + /// + /// Thrown when fails to make API call + /// + /// Object + Object ChangeAuthenticatedUserPasswordUsersMePasswordPatch(PasswordChangeAuthenticated passwordChangeAuthenticated); + + /// + /// Change Authenticated User Password + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// ApiResponse of Object + ApiResponse ChangeAuthenticatedUserPasswordUsersMePasswordPatchWithHttpInfo(PasswordChangeAuthenticated passwordChangeAuthenticated); + /// + /// Change Password Via Token + /// + /// Thrown when fails to make API call + /// + /// Object + Object ChangePasswordViaTokenUsersPasswordPatch(PasswordChangeToken passwordChangeToken); + + /// + /// Change Password Via Token + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// ApiResponse of Object + ApiResponse ChangePasswordViaTokenUsersPasswordPatchWithHttpInfo(PasswordChangeToken passwordChangeToken); + /// + /// Create User + /// + /// Thrown when fails to make API call + /// + /// FullUser + FullUser CreateUserUsersPost(NewUser newUser); + + /// + /// Create User + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// ApiResponse of FullUser + ApiResponse CreateUserUsersPostWithHttpInfo(NewUser newUser); + /// + /// Get Id User Assets + /// + /// Thrown when fails to make API call + /// + /// List<Asset> + List GetIdUserAssetsUsersIdUserAssetsGet(int user); + + /// + /// Get Id User Assets + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// ApiResponse of List<Asset> + ApiResponse> GetIdUserAssetsUsersIdUserAssetsGetWithHttpInfo(int user); + /// + /// Get Me Assets + /// + /// Thrown when fails to make API call + /// List<Asset> + List GetMeAssetsUsersMeAssetsGet(); + + /// + /// Get Me Assets + /// + /// + /// + /// + /// Thrown when fails to make API call + /// ApiResponse of List<Asset> + ApiResponse> GetMeAssetsUsersMeAssetsGetWithHttpInfo(); + /// + /// Get User Assets + /// + /// Thrown when fails to make API call + /// + /// List<Asset> + List GetUserAssetsUsersUserAssetsGet(string user); + + /// + /// Get User Assets + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// ApiResponse of List<Asset> + ApiResponse> GetUserAssetsUsersUserAssetsGetWithHttpInfo(string user); + /// + /// Get User + /// + /// Thrown when fails to make API call + /// + /// User + User GetUserUsersIdUserGet(int user); + + /// + /// Get User + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// ApiResponse of User + ApiResponse GetUserUsersIdUserGetWithHttpInfo(int user); + /// + /// Get User + /// + /// Thrown when fails to make API call + /// + /// User + User GetUserUsersUserGet(string user); + + /// + /// Get User + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// ApiResponse of User + ApiResponse GetUserUsersUserGetWithHttpInfo(string user); + /// + /// Get Users Device Code + /// + /// Thrown when fails to make API call + /// DeviceCode + DeviceCode GetUsersDeviceCodeUsersMeDevicecodeGet(); + + /// + /// Get Users Device Code + /// + /// + /// + /// + /// Thrown when fails to make API call + /// ApiResponse of DeviceCode + ApiResponse GetUsersDeviceCodeUsersMeDevicecodeGetWithHttpInfo(); + /// + /// Get Users Me + /// + /// Thrown when fails to make API call + /// FullUser + FullUser GetUsersMeUsersMeGet(); + + /// + /// Get Users Me + /// + /// + /// + /// + /// Thrown when fails to make API call + /// ApiResponse of FullUser + ApiResponse GetUsersMeUsersMeGetWithHttpInfo(); + /// + /// Update User + /// + /// Thrown when fails to make API call + /// + /// FullUser + FullUser UpdateUserUsersMePatch(PatchUser patchUser); + + /// + /// Update User + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// ApiResponse of FullUser + ApiResponse UpdateUserUsersMePatchWithHttpInfo(PatchUser patchUser); + /// + /// User Password Reset Request + /// + /// Thrown when fails to make API call + /// + /// Object + Object UserPasswordResetRequestUsersPasswordResetPut(PasswordReset passwordReset); + + /// + /// User Password Reset Request + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// ApiResponse of Object + ApiResponse UserPasswordResetRequestUsersPasswordResetPutWithHttpInfo(PasswordReset passwordReset); + #endregion Synchronous Operations + } + + /// + /// Represents a collection of functions to interact with the API endpoints + /// + public interface IUsersApiAsync : IApiAccessor + { + #region Asynchronous Operations + /// + /// Change Authenticated User Email + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of Object + System.Threading.Tasks.Task ChangeAuthenticatedUserEmailUsersMeEmailPatchAsync(EmailChangeAuthenticated emailChangeAuthenticated, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + + /// + /// Change Authenticated User Email + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of ApiResponse (Object) + System.Threading.Tasks.Task> ChangeAuthenticatedUserEmailUsersMeEmailPatchWithHttpInfoAsync(EmailChangeAuthenticated emailChangeAuthenticated, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + /// + /// Change Authenticated User Password + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of Object + System.Threading.Tasks.Task ChangeAuthenticatedUserPasswordUsersMePasswordPatchAsync(PasswordChangeAuthenticated passwordChangeAuthenticated, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + + /// + /// Change Authenticated User Password + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of ApiResponse (Object) + System.Threading.Tasks.Task> ChangeAuthenticatedUserPasswordUsersMePasswordPatchWithHttpInfoAsync(PasswordChangeAuthenticated passwordChangeAuthenticated, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + /// + /// Change Password Via Token + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of Object + System.Threading.Tasks.Task ChangePasswordViaTokenUsersPasswordPatchAsync(PasswordChangeToken passwordChangeToken, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + + /// + /// Change Password Via Token + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of ApiResponse (Object) + System.Threading.Tasks.Task> ChangePasswordViaTokenUsersPasswordPatchWithHttpInfoAsync(PasswordChangeToken passwordChangeToken, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + /// + /// Create User + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of FullUser + System.Threading.Tasks.Task CreateUserUsersPostAsync(NewUser newUser, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + + /// + /// Create User + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of ApiResponse (FullUser) + System.Threading.Tasks.Task> CreateUserUsersPostWithHttpInfoAsync(NewUser newUser, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + /// + /// Get Id User Assets + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of List<Asset> + System.Threading.Tasks.Task> GetIdUserAssetsUsersIdUserAssetsGetAsync(int user, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + + /// + /// Get Id User Assets + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of ApiResponse (List<Asset>) + System.Threading.Tasks.Task>> GetIdUserAssetsUsersIdUserAssetsGetWithHttpInfoAsync(int user, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + /// + /// Get Me Assets + /// + /// + /// + /// + /// Thrown when fails to make API call + /// Cancellation Token to cancel the request. + /// Task of List<Asset> + System.Threading.Tasks.Task> GetMeAssetsUsersMeAssetsGetAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + + /// + /// Get Me Assets + /// + /// + /// + /// + /// Thrown when fails to make API call + /// Cancellation Token to cancel the request. + /// Task of ApiResponse (List<Asset>) + System.Threading.Tasks.Task>> GetMeAssetsUsersMeAssetsGetWithHttpInfoAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + /// + /// Get User Assets + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of List<Asset> + System.Threading.Tasks.Task> GetUserAssetsUsersUserAssetsGetAsync(string user, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + + /// + /// Get User Assets + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of ApiResponse (List<Asset>) + System.Threading.Tasks.Task>> GetUserAssetsUsersUserAssetsGetWithHttpInfoAsync(string user, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + /// + /// Get User + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of User + System.Threading.Tasks.Task GetUserUsersIdUserGetAsync(int user, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + + /// + /// Get User + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of ApiResponse (User) + System.Threading.Tasks.Task> GetUserUsersIdUserGetWithHttpInfoAsync(int user, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + /// + /// Get User + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of User + System.Threading.Tasks.Task GetUserUsersUserGetAsync(string user, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + + /// + /// Get User + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of ApiResponse (User) + System.Threading.Tasks.Task> GetUserUsersUserGetWithHttpInfoAsync(string user, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + /// + /// Get Users Device Code + /// + /// + /// + /// + /// Thrown when fails to make API call + /// Cancellation Token to cancel the request. + /// Task of DeviceCode + System.Threading.Tasks.Task GetUsersDeviceCodeUsersMeDevicecodeGetAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + + /// + /// Get Users Device Code + /// + /// + /// + /// + /// Thrown when fails to make API call + /// Cancellation Token to cancel the request. + /// Task of ApiResponse (DeviceCode) + System.Threading.Tasks.Task> GetUsersDeviceCodeUsersMeDevicecodeGetWithHttpInfoAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + /// + /// Get Users Me + /// + /// + /// + /// + /// Thrown when fails to make API call + /// Cancellation Token to cancel the request. + /// Task of FullUser + System.Threading.Tasks.Task GetUsersMeUsersMeGetAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + + /// + /// Get Users Me + /// + /// + /// + /// + /// Thrown when fails to make API call + /// Cancellation Token to cancel the request. + /// Task of ApiResponse (FullUser) + System.Threading.Tasks.Task> GetUsersMeUsersMeGetWithHttpInfoAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + /// + /// Update User + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of FullUser + System.Threading.Tasks.Task UpdateUserUsersMePatchAsync(PatchUser patchUser, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + + /// + /// Update User + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of ApiResponse (FullUser) + System.Threading.Tasks.Task> UpdateUserUsersMePatchWithHttpInfoAsync(PatchUser patchUser, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + /// + /// User Password Reset Request + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of Object + System.Threading.Tasks.Task UserPasswordResetRequestUsersPasswordResetPutAsync(PasswordReset passwordReset, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + + /// + /// User Password Reset Request + /// + /// + /// + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of ApiResponse (Object) + System.Threading.Tasks.Task> UserPasswordResetRequestUsersPasswordResetPutWithHttpInfoAsync(PasswordReset passwordReset, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + #endregion Asynchronous Operations + } + + /// + /// Represents a collection of functions to interact with the API endpoints + /// + public interface IUsersApi : IUsersApiSync, IUsersApiAsync + { + + } + + /// + /// Represents a collection of functions to interact with the API endpoints + /// + public partial class UsersApi : IDisposable, IUsersApi + { + private Org.OpenAPITools.Client.ExceptionFactory _exceptionFactory = (name, response) => null; + + /// + /// Initializes a new instance of the class. + /// **IMPORTANT** This will also create an instance of HttpClient, which is less than ideal. + /// It's better to reuse the HttpClient and HttpClientHandler. + /// + /// + public UsersApi() : this((string)null) + { + } + + /// + /// Initializes a new instance of the class. + /// **IMPORTANT** This will also create an instance of HttpClient, which is less than ideal. + /// It's better to reuse the HttpClient and HttpClientHandler. + /// + /// The target service's base path in URL format. + /// + /// + public UsersApi(string basePath) + { + this.Configuration = Org.OpenAPITools.Client.Configuration.MergeConfigurations( + Org.OpenAPITools.Client.GlobalConfiguration.Instance, + new Org.OpenAPITools.Client.Configuration { BasePath = basePath } + ); + this.ApiClient = new Org.OpenAPITools.Client.ApiClient(this.Configuration.BasePath); + this.Client = this.ApiClient; + this.AsynchronousClient = this.ApiClient; + this.ExceptionFactory = Org.OpenAPITools.Client.Configuration.DefaultExceptionFactory; + } + + /// + /// Initializes a new instance of the class using Configuration object. + /// **IMPORTANT** This will also create an instance of HttpClient, which is less than ideal. + /// It's better to reuse the HttpClient and HttpClientHandler. + /// + /// An instance of Configuration. + /// + /// + public UsersApi(Org.OpenAPITools.Client.Configuration configuration) + { + if (configuration == null) throw new ArgumentNullException("configuration"); + + this.Configuration = Org.OpenAPITools.Client.Configuration.MergeConfigurations( + Org.OpenAPITools.Client.GlobalConfiguration.Instance, + configuration + ); + this.ApiClient = new Org.OpenAPITools.Client.ApiClient(this.Configuration.BasePath); + this.Client = this.ApiClient; + this.AsynchronousClient = this.ApiClient; + ExceptionFactory = Org.OpenAPITools.Client.Configuration.DefaultExceptionFactory; + } + + /// + /// Initializes a new instance of the class + /// using a Configuration object and client instance. + /// + /// The client interface for synchronous API access. + /// The client interface for asynchronous API access. + /// The configuration object. + /// + public UsersApi(Org.OpenAPITools.Client.ISynchronousClient client, Org.OpenAPITools.Client.IAsynchronousClient asyncClient, Org.OpenAPITools.Client.IReadableConfiguration configuration) + { + if (client == null) throw new ArgumentNullException("client"); + if (asyncClient == null) throw new ArgumentNullException("asyncClient"); + if (configuration == null) throw new ArgumentNullException("configuration"); + + this.Client = client; + this.AsynchronousClient = asyncClient; + this.Configuration = configuration; + this.ExceptionFactory = Org.OpenAPITools.Client.Configuration.DefaultExceptionFactory; + } + + /// + /// Disposes resources if they were created by us + /// + public void Dispose() + { + this.ApiClient?.Dispose(); + } + + /// + /// Holds the ApiClient if created + /// + public Org.OpenAPITools.Client.ApiClient ApiClient { get; set; } = null; + + /// + /// The client for accessing this underlying API asynchronously. + /// + public Org.OpenAPITools.Client.IAsynchronousClient AsynchronousClient { get; set; } + + /// + /// The client for accessing this underlying API synchronously. + /// + public Org.OpenAPITools.Client.ISynchronousClient Client { get; set; } + + /// + /// Gets the base path of the API client. + /// + /// The base path + public string GetBasePath() + { + return this.Configuration.BasePath; + } + + /// + /// Gets or sets the configuration object + /// + /// An instance of the Configuration + public Org.OpenAPITools.Client.IReadableConfiguration Configuration { get; set; } + + /// + /// Provides a factory method hook for the creation of exceptions. + /// + public Org.OpenAPITools.Client.ExceptionFactory ExceptionFactory + { + get + { + if (_exceptionFactory != null && _exceptionFactory.GetInvocationList().Length > 1) + { + throw new InvalidOperationException("Multicast delegate for ExceptionFactory is unsupported."); + } + return _exceptionFactory; + } + set { _exceptionFactory = value; } + } + + /// + /// Change Authenticated User Email + /// + /// Thrown when fails to make API call + /// + /// Object + public Object ChangeAuthenticatedUserEmailUsersMeEmailPatch(EmailChangeAuthenticated emailChangeAuthenticated) + { + Org.OpenAPITools.Client.ApiResponse localVarResponse = ChangeAuthenticatedUserEmailUsersMeEmailPatchWithHttpInfo(emailChangeAuthenticated); + return localVarResponse.Data; + } + + /// + /// Change Authenticated User Email + /// + /// Thrown when fails to make API call + /// + /// ApiResponse of Object + public Org.OpenAPITools.Client.ApiResponse ChangeAuthenticatedUserEmailUsersMeEmailPatchWithHttpInfo(EmailChangeAuthenticated emailChangeAuthenticated) + { + // verify the required parameter 'emailChangeAuthenticated' is set + if (emailChangeAuthenticated == null) + throw new Org.OpenAPITools.Client.ApiException(400, "Missing required parameter 'emailChangeAuthenticated' when calling UsersApi->ChangeAuthenticatedUserEmailUsersMeEmailPatch"); + + Org.OpenAPITools.Client.RequestOptions localVarRequestOptions = new Org.OpenAPITools.Client.RequestOptions(); + + string[] _contentTypes = new string[] { + "application/json" + }; + + // to determine the Accept header + string[] _accepts = new string[] { + "application/json" + }; + + var localVarContentType = Org.OpenAPITools.Client.ClientUtils.SelectHeaderContentType(_contentTypes); + if (localVarContentType != null) localVarRequestOptions.HeaderParameters.Add("Content-Type", localVarContentType); + + var localVarAccept = Org.OpenAPITools.Client.ClientUtils.SelectHeaderAccept(_accepts); + if (localVarAccept != null) localVarRequestOptions.HeaderParameters.Add("Accept", localVarAccept); + + localVarRequestOptions.Data = emailChangeAuthenticated; + + // authentication (OAuth2PasswordBearer) required + // oauth required + if (!string.IsNullOrEmpty(this.Configuration.AccessToken) && !localVarRequestOptions.HeaderParameters.ContainsKey("Authorization")) + { + localVarRequestOptions.HeaderParameters.Add("Authorization", "Bearer " + this.Configuration.AccessToken); + } + + // make the HTTP request + var localVarResponse = this.Client.Patch("/users/me/email", localVarRequestOptions, this.Configuration); + + if (this.ExceptionFactory != null) + { + Exception _exception = this.ExceptionFactory("ChangeAuthenticatedUserEmailUsersMeEmailPatch", localVarResponse); + if (_exception != null) throw _exception; + } + + return localVarResponse; + } + + /// + /// Change Authenticated User Email + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of Object + public async System.Threading.Tasks.Task ChangeAuthenticatedUserEmailUsersMeEmailPatchAsync(EmailChangeAuthenticated emailChangeAuthenticated, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + var task = ChangeAuthenticatedUserEmailUsersMeEmailPatchWithHttpInfoAsync(emailChangeAuthenticated, cancellationToken); +#if UNITY_EDITOR || !UNITY_WEBGL + Org.OpenAPITools.Client.ApiResponse localVarResponse = await task.ConfigureAwait(false); +#else + Org.OpenAPITools.Client.ApiResponse localVarResponse = await task; +#endif + return localVarResponse.Data; + } + + /// + /// Change Authenticated User Email + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of ApiResponse (Object) + public async System.Threading.Tasks.Task> ChangeAuthenticatedUserEmailUsersMeEmailPatchWithHttpInfoAsync(EmailChangeAuthenticated emailChangeAuthenticated, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + // verify the required parameter 'emailChangeAuthenticated' is set + if (emailChangeAuthenticated == null) + throw new Org.OpenAPITools.Client.ApiException(400, "Missing required parameter 'emailChangeAuthenticated' when calling UsersApi->ChangeAuthenticatedUserEmailUsersMeEmailPatch"); + + + Org.OpenAPITools.Client.RequestOptions localVarRequestOptions = new Org.OpenAPITools.Client.RequestOptions(); + + string[] _contentTypes = new string[] { + "application/json" + }; + + // to determine the Accept header + string[] _accepts = new string[] { + "application/json" + }; + + + var localVarContentType = Org.OpenAPITools.Client.ClientUtils.SelectHeaderContentType(_contentTypes); + if (localVarContentType != null) localVarRequestOptions.HeaderParameters.Add("Content-Type", localVarContentType); + + var localVarAccept = Org.OpenAPITools.Client.ClientUtils.SelectHeaderAccept(_accepts); + if (localVarAccept != null) localVarRequestOptions.HeaderParameters.Add("Accept", localVarAccept); + + localVarRequestOptions.Data = emailChangeAuthenticated; + + // authentication (OAuth2PasswordBearer) required + // oauth required + if (!string.IsNullOrEmpty(this.Configuration.AccessToken) && !localVarRequestOptions.HeaderParameters.ContainsKey("Authorization")) + { + localVarRequestOptions.HeaderParameters.Add("Authorization", "Bearer " + this.Configuration.AccessToken); + } + + // make the HTTP request + + var task = this.AsynchronousClient.PatchAsync("/users/me/email", localVarRequestOptions, this.Configuration, cancellationToken); + +#if UNITY_EDITOR || !UNITY_WEBGL + var localVarResponse = await task.ConfigureAwait(false); +#else + var localVarResponse = await task; +#endif + + if (this.ExceptionFactory != null) + { + Exception _exception = this.ExceptionFactory("ChangeAuthenticatedUserEmailUsersMeEmailPatch", localVarResponse); + if (_exception != null) throw _exception; + } + + return localVarResponse; + } + + /// + /// Change Authenticated User Password + /// + /// Thrown when fails to make API call + /// + /// Object + public Object ChangeAuthenticatedUserPasswordUsersMePasswordPatch(PasswordChangeAuthenticated passwordChangeAuthenticated) + { + Org.OpenAPITools.Client.ApiResponse localVarResponse = ChangeAuthenticatedUserPasswordUsersMePasswordPatchWithHttpInfo(passwordChangeAuthenticated); + return localVarResponse.Data; + } + + /// + /// Change Authenticated User Password + /// + /// Thrown when fails to make API call + /// + /// ApiResponse of Object + public Org.OpenAPITools.Client.ApiResponse ChangeAuthenticatedUserPasswordUsersMePasswordPatchWithHttpInfo(PasswordChangeAuthenticated passwordChangeAuthenticated) + { + // verify the required parameter 'passwordChangeAuthenticated' is set + if (passwordChangeAuthenticated == null) + throw new Org.OpenAPITools.Client.ApiException(400, "Missing required parameter 'passwordChangeAuthenticated' when calling UsersApi->ChangeAuthenticatedUserPasswordUsersMePasswordPatch"); + + Org.OpenAPITools.Client.RequestOptions localVarRequestOptions = new Org.OpenAPITools.Client.RequestOptions(); + + string[] _contentTypes = new string[] { + "application/json" + }; + + // to determine the Accept header + string[] _accepts = new string[] { + "application/json" + }; + + var localVarContentType = Org.OpenAPITools.Client.ClientUtils.SelectHeaderContentType(_contentTypes); + if (localVarContentType != null) localVarRequestOptions.HeaderParameters.Add("Content-Type", localVarContentType); + + var localVarAccept = Org.OpenAPITools.Client.ClientUtils.SelectHeaderAccept(_accepts); + if (localVarAccept != null) localVarRequestOptions.HeaderParameters.Add("Accept", localVarAccept); + + localVarRequestOptions.Data = passwordChangeAuthenticated; + + // authentication (OAuth2PasswordBearer) required + // oauth required + if (!string.IsNullOrEmpty(this.Configuration.AccessToken) && !localVarRequestOptions.HeaderParameters.ContainsKey("Authorization")) + { + localVarRequestOptions.HeaderParameters.Add("Authorization", "Bearer " + this.Configuration.AccessToken); + } + + // make the HTTP request + var localVarResponse = this.Client.Patch("/users/me/password", localVarRequestOptions, this.Configuration); + + if (this.ExceptionFactory != null) + { + Exception _exception = this.ExceptionFactory("ChangeAuthenticatedUserPasswordUsersMePasswordPatch", localVarResponse); + if (_exception != null) throw _exception; + } + + return localVarResponse; + } + + /// + /// Change Authenticated User Password + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of Object + public async System.Threading.Tasks.Task ChangeAuthenticatedUserPasswordUsersMePasswordPatchAsync(PasswordChangeAuthenticated passwordChangeAuthenticated, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + var task = ChangeAuthenticatedUserPasswordUsersMePasswordPatchWithHttpInfoAsync(passwordChangeAuthenticated, cancellationToken); +#if UNITY_EDITOR || !UNITY_WEBGL + Org.OpenAPITools.Client.ApiResponse localVarResponse = await task.ConfigureAwait(false); +#else + Org.OpenAPITools.Client.ApiResponse localVarResponse = await task; +#endif + return localVarResponse.Data; + } + + /// + /// Change Authenticated User Password + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of ApiResponse (Object) + public async System.Threading.Tasks.Task> ChangeAuthenticatedUserPasswordUsersMePasswordPatchWithHttpInfoAsync(PasswordChangeAuthenticated passwordChangeAuthenticated, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + // verify the required parameter 'passwordChangeAuthenticated' is set + if (passwordChangeAuthenticated == null) + throw new Org.OpenAPITools.Client.ApiException(400, "Missing required parameter 'passwordChangeAuthenticated' when calling UsersApi->ChangeAuthenticatedUserPasswordUsersMePasswordPatch"); + + + Org.OpenAPITools.Client.RequestOptions localVarRequestOptions = new Org.OpenAPITools.Client.RequestOptions(); + + string[] _contentTypes = new string[] { + "application/json" + }; + + // to determine the Accept header + string[] _accepts = new string[] { + "application/json" + }; + + + var localVarContentType = Org.OpenAPITools.Client.ClientUtils.SelectHeaderContentType(_contentTypes); + if (localVarContentType != null) localVarRequestOptions.HeaderParameters.Add("Content-Type", localVarContentType); + + var localVarAccept = Org.OpenAPITools.Client.ClientUtils.SelectHeaderAccept(_accepts); + if (localVarAccept != null) localVarRequestOptions.HeaderParameters.Add("Accept", localVarAccept); + + localVarRequestOptions.Data = passwordChangeAuthenticated; + + // authentication (OAuth2PasswordBearer) required + // oauth required + if (!string.IsNullOrEmpty(this.Configuration.AccessToken) && !localVarRequestOptions.HeaderParameters.ContainsKey("Authorization")) + { + localVarRequestOptions.HeaderParameters.Add("Authorization", "Bearer " + this.Configuration.AccessToken); + } + + // make the HTTP request + + var task = this.AsynchronousClient.PatchAsync("/users/me/password", localVarRequestOptions, this.Configuration, cancellationToken); + +#if UNITY_EDITOR || !UNITY_WEBGL + var localVarResponse = await task.ConfigureAwait(false); +#else + var localVarResponse = await task; +#endif + + if (this.ExceptionFactory != null) + { + Exception _exception = this.ExceptionFactory("ChangeAuthenticatedUserPasswordUsersMePasswordPatch", localVarResponse); + if (_exception != null) throw _exception; + } + + return localVarResponse; + } + + /// + /// Change Password Via Token + /// + /// Thrown when fails to make API call + /// + /// Object + public Object ChangePasswordViaTokenUsersPasswordPatch(PasswordChangeToken passwordChangeToken) + { + Org.OpenAPITools.Client.ApiResponse localVarResponse = ChangePasswordViaTokenUsersPasswordPatchWithHttpInfo(passwordChangeToken); + return localVarResponse.Data; + } + + /// + /// Change Password Via Token + /// + /// Thrown when fails to make API call + /// + /// ApiResponse of Object + public Org.OpenAPITools.Client.ApiResponse ChangePasswordViaTokenUsersPasswordPatchWithHttpInfo(PasswordChangeToken passwordChangeToken) + { + // verify the required parameter 'passwordChangeToken' is set + if (passwordChangeToken == null) + throw new Org.OpenAPITools.Client.ApiException(400, "Missing required parameter 'passwordChangeToken' when calling UsersApi->ChangePasswordViaTokenUsersPasswordPatch"); + + Org.OpenAPITools.Client.RequestOptions localVarRequestOptions = new Org.OpenAPITools.Client.RequestOptions(); + + string[] _contentTypes = new string[] { + "application/json" + }; + + // to determine the Accept header + string[] _accepts = new string[] { + "application/json" + }; + + var localVarContentType = Org.OpenAPITools.Client.ClientUtils.SelectHeaderContentType(_contentTypes); + if (localVarContentType != null) localVarRequestOptions.HeaderParameters.Add("Content-Type", localVarContentType); + + var localVarAccept = Org.OpenAPITools.Client.ClientUtils.SelectHeaderAccept(_accepts); + if (localVarAccept != null) localVarRequestOptions.HeaderParameters.Add("Accept", localVarAccept); + + localVarRequestOptions.Data = passwordChangeToken; + + + // make the HTTP request + var localVarResponse = this.Client.Patch("/users/password", localVarRequestOptions, this.Configuration); + + if (this.ExceptionFactory != null) + { + Exception _exception = this.ExceptionFactory("ChangePasswordViaTokenUsersPasswordPatch", localVarResponse); + if (_exception != null) throw _exception; + } + + return localVarResponse; + } + + /// + /// Change Password Via Token + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of Object + public async System.Threading.Tasks.Task ChangePasswordViaTokenUsersPasswordPatchAsync(PasswordChangeToken passwordChangeToken, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + var task = ChangePasswordViaTokenUsersPasswordPatchWithHttpInfoAsync(passwordChangeToken, cancellationToken); +#if UNITY_EDITOR || !UNITY_WEBGL + Org.OpenAPITools.Client.ApiResponse localVarResponse = await task.ConfigureAwait(false); +#else + Org.OpenAPITools.Client.ApiResponse localVarResponse = await task; +#endif + return localVarResponse.Data; + } + + /// + /// Change Password Via Token + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of ApiResponse (Object) + public async System.Threading.Tasks.Task> ChangePasswordViaTokenUsersPasswordPatchWithHttpInfoAsync(PasswordChangeToken passwordChangeToken, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + // verify the required parameter 'passwordChangeToken' is set + if (passwordChangeToken == null) + throw new Org.OpenAPITools.Client.ApiException(400, "Missing required parameter 'passwordChangeToken' when calling UsersApi->ChangePasswordViaTokenUsersPasswordPatch"); + + + Org.OpenAPITools.Client.RequestOptions localVarRequestOptions = new Org.OpenAPITools.Client.RequestOptions(); + + string[] _contentTypes = new string[] { + "application/json" + }; + + // to determine the Accept header + string[] _accepts = new string[] { + "application/json" + }; + + + var localVarContentType = Org.OpenAPITools.Client.ClientUtils.SelectHeaderContentType(_contentTypes); + if (localVarContentType != null) localVarRequestOptions.HeaderParameters.Add("Content-Type", localVarContentType); + + var localVarAccept = Org.OpenAPITools.Client.ClientUtils.SelectHeaderAccept(_accepts); + if (localVarAccept != null) localVarRequestOptions.HeaderParameters.Add("Accept", localVarAccept); + + localVarRequestOptions.Data = passwordChangeToken; + + + // make the HTTP request + + var task = this.AsynchronousClient.PatchAsync("/users/password", localVarRequestOptions, this.Configuration, cancellationToken); + +#if UNITY_EDITOR || !UNITY_WEBGL + var localVarResponse = await task.ConfigureAwait(false); +#else + var localVarResponse = await task; +#endif + + if (this.ExceptionFactory != null) + { + Exception _exception = this.ExceptionFactory("ChangePasswordViaTokenUsersPasswordPatch", localVarResponse); + if (_exception != null) throw _exception; + } + + return localVarResponse; + } + + /// + /// Create User + /// + /// Thrown when fails to make API call + /// + /// FullUser + public FullUser CreateUserUsersPost(NewUser newUser) + { + Org.OpenAPITools.Client.ApiResponse localVarResponse = CreateUserUsersPostWithHttpInfo(newUser); + return localVarResponse.Data; + } + + /// + /// Create User + /// + /// Thrown when fails to make API call + /// + /// ApiResponse of FullUser + public Org.OpenAPITools.Client.ApiResponse CreateUserUsersPostWithHttpInfo(NewUser newUser) + { + // verify the required parameter 'newUser' is set + if (newUser == null) + throw new Org.OpenAPITools.Client.ApiException(400, "Missing required parameter 'newUser' when calling UsersApi->CreateUserUsersPost"); + + Org.OpenAPITools.Client.RequestOptions localVarRequestOptions = new Org.OpenAPITools.Client.RequestOptions(); + + string[] _contentTypes = new string[] { + "application/json" + }; + + // to determine the Accept header + string[] _accepts = new string[] { + "application/json" + }; + + var localVarContentType = Org.OpenAPITools.Client.ClientUtils.SelectHeaderContentType(_contentTypes); + if (localVarContentType != null) localVarRequestOptions.HeaderParameters.Add("Content-Type", localVarContentType); + + var localVarAccept = Org.OpenAPITools.Client.ClientUtils.SelectHeaderAccept(_accepts); + if (localVarAccept != null) localVarRequestOptions.HeaderParameters.Add("Accept", localVarAccept); + + localVarRequestOptions.Data = newUser; + + + // make the HTTP request + var localVarResponse = this.Client.Post("/users", localVarRequestOptions, this.Configuration); + + if (this.ExceptionFactory != null) + { + Exception _exception = this.ExceptionFactory("CreateUserUsersPost", localVarResponse); + if (_exception != null) throw _exception; + } + + return localVarResponse; + } + + /// + /// Create User + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of FullUser + public async System.Threading.Tasks.Task CreateUserUsersPostAsync(NewUser newUser, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + var task = CreateUserUsersPostWithHttpInfoAsync(newUser, cancellationToken); +#if UNITY_EDITOR || !UNITY_WEBGL + Org.OpenAPITools.Client.ApiResponse localVarResponse = await task.ConfigureAwait(false); +#else + Org.OpenAPITools.Client.ApiResponse localVarResponse = await task; +#endif + return localVarResponse.Data; + } + + /// + /// Create User + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of ApiResponse (FullUser) + public async System.Threading.Tasks.Task> CreateUserUsersPostWithHttpInfoAsync(NewUser newUser, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + // verify the required parameter 'newUser' is set + if (newUser == null) + throw new Org.OpenAPITools.Client.ApiException(400, "Missing required parameter 'newUser' when calling UsersApi->CreateUserUsersPost"); + + + Org.OpenAPITools.Client.RequestOptions localVarRequestOptions = new Org.OpenAPITools.Client.RequestOptions(); + + string[] _contentTypes = new string[] { + "application/json" + }; + + // to determine the Accept header + string[] _accepts = new string[] { + "application/json" + }; + + + var localVarContentType = Org.OpenAPITools.Client.ClientUtils.SelectHeaderContentType(_contentTypes); + if (localVarContentType != null) localVarRequestOptions.HeaderParameters.Add("Content-Type", localVarContentType); + + var localVarAccept = Org.OpenAPITools.Client.ClientUtils.SelectHeaderAccept(_accepts); + if (localVarAccept != null) localVarRequestOptions.HeaderParameters.Add("Accept", localVarAccept); + + localVarRequestOptions.Data = newUser; + + + // make the HTTP request + + var task = this.AsynchronousClient.PostAsync("/users", localVarRequestOptions, this.Configuration, cancellationToken); + +#if UNITY_EDITOR || !UNITY_WEBGL + var localVarResponse = await task.ConfigureAwait(false); +#else + var localVarResponse = await task; +#endif + + if (this.ExceptionFactory != null) + { + Exception _exception = this.ExceptionFactory("CreateUserUsersPost", localVarResponse); + if (_exception != null) throw _exception; + } + + return localVarResponse; + } + + /// + /// Get Id User Assets + /// + /// Thrown when fails to make API call + /// + /// List<Asset> + public List GetIdUserAssetsUsersIdUserAssetsGet(int user) + { + Org.OpenAPITools.Client.ApiResponse> localVarResponse = GetIdUserAssetsUsersIdUserAssetsGetWithHttpInfo(user); + return localVarResponse.Data; + } + + /// + /// Get Id User Assets + /// + /// Thrown when fails to make API call + /// + /// ApiResponse of List<Asset> + public Org.OpenAPITools.Client.ApiResponse> GetIdUserAssetsUsersIdUserAssetsGetWithHttpInfo(int user) + { + Org.OpenAPITools.Client.RequestOptions localVarRequestOptions = new Org.OpenAPITools.Client.RequestOptions(); + + string[] _contentTypes = new string[] { + }; + + // to determine the Accept header + string[] _accepts = new string[] { + "application/json" + }; + + var localVarContentType = Org.OpenAPITools.Client.ClientUtils.SelectHeaderContentType(_contentTypes); + if (localVarContentType != null) localVarRequestOptions.HeaderParameters.Add("Content-Type", localVarContentType); + + var localVarAccept = Org.OpenAPITools.Client.ClientUtils.SelectHeaderAccept(_accepts); + if (localVarAccept != null) localVarRequestOptions.HeaderParameters.Add("Accept", localVarAccept); + + localVarRequestOptions.PathParameters.Add("user", Org.OpenAPITools.Client.ClientUtils.ParameterToString(user)); // path parameter + + // authentication (OAuth2PasswordBearer) required + // oauth required + if (!string.IsNullOrEmpty(this.Configuration.AccessToken) && !localVarRequestOptions.HeaderParameters.ContainsKey("Authorization")) + { + localVarRequestOptions.HeaderParameters.Add("Authorization", "Bearer " + this.Configuration.AccessToken); + } + + // make the HTTP request + var localVarResponse = this.Client.Get>("/users/id/{user}/assets", localVarRequestOptions, this.Configuration); + + if (this.ExceptionFactory != null) + { + Exception _exception = this.ExceptionFactory("GetIdUserAssetsUsersIdUserAssetsGet", localVarResponse); + if (_exception != null) throw _exception; + } + + return localVarResponse; + } + + /// + /// Get Id User Assets + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of List<Asset> + public async System.Threading.Tasks.Task> GetIdUserAssetsUsersIdUserAssetsGetAsync(int user, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + var task = GetIdUserAssetsUsersIdUserAssetsGetWithHttpInfoAsync(user, cancellationToken); +#if UNITY_EDITOR || !UNITY_WEBGL + Org.OpenAPITools.Client.ApiResponse> localVarResponse = await task.ConfigureAwait(false); +#else + Org.OpenAPITools.Client.ApiResponse> localVarResponse = await task; +#endif + return localVarResponse.Data; + } + + /// + /// Get Id User Assets + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of ApiResponse (List<Asset>) + public async System.Threading.Tasks.Task>> GetIdUserAssetsUsersIdUserAssetsGetWithHttpInfoAsync(int user, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + + Org.OpenAPITools.Client.RequestOptions localVarRequestOptions = new Org.OpenAPITools.Client.RequestOptions(); + + string[] _contentTypes = new string[] { + }; + + // to determine the Accept header + string[] _accepts = new string[] { + "application/json" + }; + + + var localVarContentType = Org.OpenAPITools.Client.ClientUtils.SelectHeaderContentType(_contentTypes); + if (localVarContentType != null) localVarRequestOptions.HeaderParameters.Add("Content-Type", localVarContentType); + + var localVarAccept = Org.OpenAPITools.Client.ClientUtils.SelectHeaderAccept(_accepts); + if (localVarAccept != null) localVarRequestOptions.HeaderParameters.Add("Accept", localVarAccept); + + localVarRequestOptions.PathParameters.Add("user", Org.OpenAPITools.Client.ClientUtils.ParameterToString(user)); // path parameter + + // authentication (OAuth2PasswordBearer) required + // oauth required + if (!string.IsNullOrEmpty(this.Configuration.AccessToken) && !localVarRequestOptions.HeaderParameters.ContainsKey("Authorization")) + { + localVarRequestOptions.HeaderParameters.Add("Authorization", "Bearer " + this.Configuration.AccessToken); + } + + // make the HTTP request + + var task = this.AsynchronousClient.GetAsync>("/users/id/{user}/assets", localVarRequestOptions, this.Configuration, cancellationToken); + +#if UNITY_EDITOR || !UNITY_WEBGL + var localVarResponse = await task.ConfigureAwait(false); +#else + var localVarResponse = await task; +#endif + + if (this.ExceptionFactory != null) + { + Exception _exception = this.ExceptionFactory("GetIdUserAssetsUsersIdUserAssetsGet", localVarResponse); + if (_exception != null) throw _exception; + } + + return localVarResponse; + } + + /// + /// Get Me Assets + /// + /// Thrown when fails to make API call + /// List<Asset> + public List GetMeAssetsUsersMeAssetsGet() + { + Org.OpenAPITools.Client.ApiResponse> localVarResponse = GetMeAssetsUsersMeAssetsGetWithHttpInfo(); + return localVarResponse.Data; + } + + /// + /// Get Me Assets + /// + /// Thrown when fails to make API call + /// ApiResponse of List<Asset> + public Org.OpenAPITools.Client.ApiResponse> GetMeAssetsUsersMeAssetsGetWithHttpInfo() + { + Org.OpenAPITools.Client.RequestOptions localVarRequestOptions = new Org.OpenAPITools.Client.RequestOptions(); + + string[] _contentTypes = new string[] { + }; + + // to determine the Accept header + string[] _accepts = new string[] { + "application/json" + }; + + var localVarContentType = Org.OpenAPITools.Client.ClientUtils.SelectHeaderContentType(_contentTypes); + if (localVarContentType != null) localVarRequestOptions.HeaderParameters.Add("Content-Type", localVarContentType); + + var localVarAccept = Org.OpenAPITools.Client.ClientUtils.SelectHeaderAccept(_accepts); + if (localVarAccept != null) localVarRequestOptions.HeaderParameters.Add("Accept", localVarAccept); + + + // authentication (OAuth2PasswordBearer) required + // oauth required + if (!string.IsNullOrEmpty(this.Configuration.AccessToken) && !localVarRequestOptions.HeaderParameters.ContainsKey("Authorization")) + { + localVarRequestOptions.HeaderParameters.Add("Authorization", "Bearer " + this.Configuration.AccessToken); + } + + // make the HTTP request + var localVarResponse = this.Client.Get>("/users/me/assets", localVarRequestOptions, this.Configuration); + + if (this.ExceptionFactory != null) + { + Exception _exception = this.ExceptionFactory("GetMeAssetsUsersMeAssetsGet", localVarResponse); + if (_exception != null) throw _exception; + } + + return localVarResponse; + } + + /// + /// Get Me Assets + /// + /// Thrown when fails to make API call + /// Cancellation Token to cancel the request. + /// Task of List<Asset> + public async System.Threading.Tasks.Task> GetMeAssetsUsersMeAssetsGetAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + var task = GetMeAssetsUsersMeAssetsGetWithHttpInfoAsync(cancellationToken); +#if UNITY_EDITOR || !UNITY_WEBGL + Org.OpenAPITools.Client.ApiResponse> localVarResponse = await task.ConfigureAwait(false); +#else + Org.OpenAPITools.Client.ApiResponse> localVarResponse = await task; +#endif + return localVarResponse.Data; + } + + /// + /// Get Me Assets + /// + /// Thrown when fails to make API call + /// Cancellation Token to cancel the request. + /// Task of ApiResponse (List<Asset>) + public async System.Threading.Tasks.Task>> GetMeAssetsUsersMeAssetsGetWithHttpInfoAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + + Org.OpenAPITools.Client.RequestOptions localVarRequestOptions = new Org.OpenAPITools.Client.RequestOptions(); + + string[] _contentTypes = new string[] { + }; + + // to determine the Accept header + string[] _accepts = new string[] { + "application/json" + }; + + + var localVarContentType = Org.OpenAPITools.Client.ClientUtils.SelectHeaderContentType(_contentTypes); + if (localVarContentType != null) localVarRequestOptions.HeaderParameters.Add("Content-Type", localVarContentType); + + var localVarAccept = Org.OpenAPITools.Client.ClientUtils.SelectHeaderAccept(_accepts); + if (localVarAccept != null) localVarRequestOptions.HeaderParameters.Add("Accept", localVarAccept); + + + // authentication (OAuth2PasswordBearer) required + // oauth required + if (!string.IsNullOrEmpty(this.Configuration.AccessToken) && !localVarRequestOptions.HeaderParameters.ContainsKey("Authorization")) + { + localVarRequestOptions.HeaderParameters.Add("Authorization", "Bearer " + this.Configuration.AccessToken); + } + + // make the HTTP request + + var task = this.AsynchronousClient.GetAsync>("/users/me/assets", localVarRequestOptions, this.Configuration, cancellationToken); + +#if UNITY_EDITOR || !UNITY_WEBGL + var localVarResponse = await task.ConfigureAwait(false); +#else + var localVarResponse = await task; +#endif + + if (this.ExceptionFactory != null) + { + Exception _exception = this.ExceptionFactory("GetMeAssetsUsersMeAssetsGet", localVarResponse); + if (_exception != null) throw _exception; + } + + return localVarResponse; + } + + /// + /// Get User Assets + /// + /// Thrown when fails to make API call + /// + /// List<Asset> + public List GetUserAssetsUsersUserAssetsGet(string user) + { + Org.OpenAPITools.Client.ApiResponse> localVarResponse = GetUserAssetsUsersUserAssetsGetWithHttpInfo(user); + return localVarResponse.Data; + } + + /// + /// Get User Assets + /// + /// Thrown when fails to make API call + /// + /// ApiResponse of List<Asset> + public Org.OpenAPITools.Client.ApiResponse> GetUserAssetsUsersUserAssetsGetWithHttpInfo(string user) + { + // verify the required parameter 'user' is set + if (user == null) + throw new Org.OpenAPITools.Client.ApiException(400, "Missing required parameter 'user' when calling UsersApi->GetUserAssetsUsersUserAssetsGet"); + + Org.OpenAPITools.Client.RequestOptions localVarRequestOptions = new Org.OpenAPITools.Client.RequestOptions(); + + string[] _contentTypes = new string[] { + }; + + // to determine the Accept header + string[] _accepts = new string[] { + "application/json" + }; + + var localVarContentType = Org.OpenAPITools.Client.ClientUtils.SelectHeaderContentType(_contentTypes); + if (localVarContentType != null) localVarRequestOptions.HeaderParameters.Add("Content-Type", localVarContentType); + + var localVarAccept = Org.OpenAPITools.Client.ClientUtils.SelectHeaderAccept(_accepts); + if (localVarAccept != null) localVarRequestOptions.HeaderParameters.Add("Accept", localVarAccept); + + localVarRequestOptions.PathParameters.Add("user", Org.OpenAPITools.Client.ClientUtils.ParameterToString(user)); // path parameter + + // authentication (OAuth2PasswordBearer) required + // oauth required + if (!string.IsNullOrEmpty(this.Configuration.AccessToken) && !localVarRequestOptions.HeaderParameters.ContainsKey("Authorization")) + { + localVarRequestOptions.HeaderParameters.Add("Authorization", "Bearer " + this.Configuration.AccessToken); + } + + // make the HTTP request + var localVarResponse = this.Client.Get>("/users/{user}/assets", localVarRequestOptions, this.Configuration); + + if (this.ExceptionFactory != null) + { + Exception _exception = this.ExceptionFactory("GetUserAssetsUsersUserAssetsGet", localVarResponse); + if (_exception != null) throw _exception; + } + + return localVarResponse; + } + + /// + /// Get User Assets + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of List<Asset> + public async System.Threading.Tasks.Task> GetUserAssetsUsersUserAssetsGetAsync(string user, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + var task = GetUserAssetsUsersUserAssetsGetWithHttpInfoAsync(user, cancellationToken); +#if UNITY_EDITOR || !UNITY_WEBGL + Org.OpenAPITools.Client.ApiResponse> localVarResponse = await task.ConfigureAwait(false); +#else + Org.OpenAPITools.Client.ApiResponse> localVarResponse = await task; +#endif + return localVarResponse.Data; + } + + /// + /// Get User Assets + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of ApiResponse (List<Asset>) + public async System.Threading.Tasks.Task>> GetUserAssetsUsersUserAssetsGetWithHttpInfoAsync(string user, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + // verify the required parameter 'user' is set + if (user == null) + throw new Org.OpenAPITools.Client.ApiException(400, "Missing required parameter 'user' when calling UsersApi->GetUserAssetsUsersUserAssetsGet"); + + + Org.OpenAPITools.Client.RequestOptions localVarRequestOptions = new Org.OpenAPITools.Client.RequestOptions(); + + string[] _contentTypes = new string[] { + }; + + // to determine the Accept header + string[] _accepts = new string[] { + "application/json" + }; + + + var localVarContentType = Org.OpenAPITools.Client.ClientUtils.SelectHeaderContentType(_contentTypes); + if (localVarContentType != null) localVarRequestOptions.HeaderParameters.Add("Content-Type", localVarContentType); + + var localVarAccept = Org.OpenAPITools.Client.ClientUtils.SelectHeaderAccept(_accepts); + if (localVarAccept != null) localVarRequestOptions.HeaderParameters.Add("Accept", localVarAccept); + + localVarRequestOptions.PathParameters.Add("user", Org.OpenAPITools.Client.ClientUtils.ParameterToString(user)); // path parameter + + // authentication (OAuth2PasswordBearer) required + // oauth required + if (!string.IsNullOrEmpty(this.Configuration.AccessToken) && !localVarRequestOptions.HeaderParameters.ContainsKey("Authorization")) + { + localVarRequestOptions.HeaderParameters.Add("Authorization", "Bearer " + this.Configuration.AccessToken); + } + + // make the HTTP request + + var task = this.AsynchronousClient.GetAsync>("/users/{user}/assets", localVarRequestOptions, this.Configuration, cancellationToken); + +#if UNITY_EDITOR || !UNITY_WEBGL + var localVarResponse = await task.ConfigureAwait(false); +#else + var localVarResponse = await task; +#endif + + if (this.ExceptionFactory != null) + { + Exception _exception = this.ExceptionFactory("GetUserAssetsUsersUserAssetsGet", localVarResponse); + if (_exception != null) throw _exception; + } + + return localVarResponse; + } + + /// + /// Get User + /// + /// Thrown when fails to make API call + /// + /// User + public User GetUserUsersIdUserGet(int user) + { + Org.OpenAPITools.Client.ApiResponse localVarResponse = GetUserUsersIdUserGetWithHttpInfo(user); + return localVarResponse.Data; + } + + /// + /// Get User + /// + /// Thrown when fails to make API call + /// + /// ApiResponse of User + public Org.OpenAPITools.Client.ApiResponse GetUserUsersIdUserGetWithHttpInfo(int user) + { + Org.OpenAPITools.Client.RequestOptions localVarRequestOptions = new Org.OpenAPITools.Client.RequestOptions(); + + string[] _contentTypes = new string[] { + }; + + // to determine the Accept header + string[] _accepts = new string[] { + "application/json" + }; + + var localVarContentType = Org.OpenAPITools.Client.ClientUtils.SelectHeaderContentType(_contentTypes); + if (localVarContentType != null) localVarRequestOptions.HeaderParameters.Add("Content-Type", localVarContentType); + + var localVarAccept = Org.OpenAPITools.Client.ClientUtils.SelectHeaderAccept(_accepts); + if (localVarAccept != null) localVarRequestOptions.HeaderParameters.Add("Accept", localVarAccept); + + localVarRequestOptions.PathParameters.Add("user", Org.OpenAPITools.Client.ClientUtils.ParameterToString(user)); // path parameter + + + // make the HTTP request + var localVarResponse = this.Client.Get("/users/id/{user}", localVarRequestOptions, this.Configuration); + + if (this.ExceptionFactory != null) + { + Exception _exception = this.ExceptionFactory("GetUserUsersIdUserGet", localVarResponse); + if (_exception != null) throw _exception; + } + + return localVarResponse; + } + + /// + /// Get User + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of User + public async System.Threading.Tasks.Task GetUserUsersIdUserGetAsync(int user, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + var task = GetUserUsersIdUserGetWithHttpInfoAsync(user, cancellationToken); +#if UNITY_EDITOR || !UNITY_WEBGL + Org.OpenAPITools.Client.ApiResponse localVarResponse = await task.ConfigureAwait(false); +#else + Org.OpenAPITools.Client.ApiResponse localVarResponse = await task; +#endif + return localVarResponse.Data; + } + + /// + /// Get User + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of ApiResponse (User) + public async System.Threading.Tasks.Task> GetUserUsersIdUserGetWithHttpInfoAsync(int user, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + + Org.OpenAPITools.Client.RequestOptions localVarRequestOptions = new Org.OpenAPITools.Client.RequestOptions(); + + string[] _contentTypes = new string[] { + }; + + // to determine the Accept header + string[] _accepts = new string[] { + "application/json" + }; + + + var localVarContentType = Org.OpenAPITools.Client.ClientUtils.SelectHeaderContentType(_contentTypes); + if (localVarContentType != null) localVarRequestOptions.HeaderParameters.Add("Content-Type", localVarContentType); + + var localVarAccept = Org.OpenAPITools.Client.ClientUtils.SelectHeaderAccept(_accepts); + if (localVarAccept != null) localVarRequestOptions.HeaderParameters.Add("Accept", localVarAccept); + + localVarRequestOptions.PathParameters.Add("user", Org.OpenAPITools.Client.ClientUtils.ParameterToString(user)); // path parameter + + + // make the HTTP request + + var task = this.AsynchronousClient.GetAsync("/users/id/{user}", localVarRequestOptions, this.Configuration, cancellationToken); + +#if UNITY_EDITOR || !UNITY_WEBGL + var localVarResponse = await task.ConfigureAwait(false); +#else + var localVarResponse = await task; +#endif + + if (this.ExceptionFactory != null) + { + Exception _exception = this.ExceptionFactory("GetUserUsersIdUserGet", localVarResponse); + if (_exception != null) throw _exception; + } + + return localVarResponse; + } + + /// + /// Get User + /// + /// Thrown when fails to make API call + /// + /// User + public User GetUserUsersUserGet(string user) + { + Org.OpenAPITools.Client.ApiResponse localVarResponse = GetUserUsersUserGetWithHttpInfo(user); + return localVarResponse.Data; + } + + /// + /// Get User + /// + /// Thrown when fails to make API call + /// + /// ApiResponse of User + public Org.OpenAPITools.Client.ApiResponse GetUserUsersUserGetWithHttpInfo(string user) + { + // verify the required parameter 'user' is set + if (user == null) + throw new Org.OpenAPITools.Client.ApiException(400, "Missing required parameter 'user' when calling UsersApi->GetUserUsersUserGet"); + + Org.OpenAPITools.Client.RequestOptions localVarRequestOptions = new Org.OpenAPITools.Client.RequestOptions(); + + string[] _contentTypes = new string[] { + }; + + // to determine the Accept header + string[] _accepts = new string[] { + "application/json" + }; + + var localVarContentType = Org.OpenAPITools.Client.ClientUtils.SelectHeaderContentType(_contentTypes); + if (localVarContentType != null) localVarRequestOptions.HeaderParameters.Add("Content-Type", localVarContentType); + + var localVarAccept = Org.OpenAPITools.Client.ClientUtils.SelectHeaderAccept(_accepts); + if (localVarAccept != null) localVarRequestOptions.HeaderParameters.Add("Accept", localVarAccept); + + localVarRequestOptions.PathParameters.Add("user", Org.OpenAPITools.Client.ClientUtils.ParameterToString(user)); // path parameter + + + // make the HTTP request + var localVarResponse = this.Client.Get("/users/{user}", localVarRequestOptions, this.Configuration); + + if (this.ExceptionFactory != null) + { + Exception _exception = this.ExceptionFactory("GetUserUsersUserGet", localVarResponse); + if (_exception != null) throw _exception; + } + + return localVarResponse; + } + + /// + /// Get User + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of User + public async System.Threading.Tasks.Task GetUserUsersUserGetAsync(string user, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + var task = GetUserUsersUserGetWithHttpInfoAsync(user, cancellationToken); +#if UNITY_EDITOR || !UNITY_WEBGL + Org.OpenAPITools.Client.ApiResponse localVarResponse = await task.ConfigureAwait(false); +#else + Org.OpenAPITools.Client.ApiResponse localVarResponse = await task; +#endif + return localVarResponse.Data; + } + + /// + /// Get User + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of ApiResponse (User) + public async System.Threading.Tasks.Task> GetUserUsersUserGetWithHttpInfoAsync(string user, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + // verify the required parameter 'user' is set + if (user == null) + throw new Org.OpenAPITools.Client.ApiException(400, "Missing required parameter 'user' when calling UsersApi->GetUserUsersUserGet"); + + + Org.OpenAPITools.Client.RequestOptions localVarRequestOptions = new Org.OpenAPITools.Client.RequestOptions(); + + string[] _contentTypes = new string[] { + }; + + // to determine the Accept header + string[] _accepts = new string[] { + "application/json" + }; + + + var localVarContentType = Org.OpenAPITools.Client.ClientUtils.SelectHeaderContentType(_contentTypes); + if (localVarContentType != null) localVarRequestOptions.HeaderParameters.Add("Content-Type", localVarContentType); + + var localVarAccept = Org.OpenAPITools.Client.ClientUtils.SelectHeaderAccept(_accepts); + if (localVarAccept != null) localVarRequestOptions.HeaderParameters.Add("Accept", localVarAccept); + + localVarRequestOptions.PathParameters.Add("user", Org.OpenAPITools.Client.ClientUtils.ParameterToString(user)); // path parameter + + + // make the HTTP request + + var task = this.AsynchronousClient.GetAsync("/users/{user}", localVarRequestOptions, this.Configuration, cancellationToken); + +#if UNITY_EDITOR || !UNITY_WEBGL + var localVarResponse = await task.ConfigureAwait(false); +#else + var localVarResponse = await task; +#endif + + if (this.ExceptionFactory != null) + { + Exception _exception = this.ExceptionFactory("GetUserUsersUserGet", localVarResponse); + if (_exception != null) throw _exception; + } + + return localVarResponse; + } + + /// + /// Get Users Device Code + /// + /// Thrown when fails to make API call + /// DeviceCode + public DeviceCode GetUsersDeviceCodeUsersMeDevicecodeGet() + { + Org.OpenAPITools.Client.ApiResponse localVarResponse = GetUsersDeviceCodeUsersMeDevicecodeGetWithHttpInfo(); + return localVarResponse.Data; + } + + /// + /// Get Users Device Code + /// + /// Thrown when fails to make API call + /// ApiResponse of DeviceCode + public Org.OpenAPITools.Client.ApiResponse GetUsersDeviceCodeUsersMeDevicecodeGetWithHttpInfo() + { + Org.OpenAPITools.Client.RequestOptions localVarRequestOptions = new Org.OpenAPITools.Client.RequestOptions(); + + string[] _contentTypes = new string[] { + }; + + // to determine the Accept header + string[] _accepts = new string[] { + "application/json" + }; + + var localVarContentType = Org.OpenAPITools.Client.ClientUtils.SelectHeaderContentType(_contentTypes); + if (localVarContentType != null) localVarRequestOptions.HeaderParameters.Add("Content-Type", localVarContentType); + + var localVarAccept = Org.OpenAPITools.Client.ClientUtils.SelectHeaderAccept(_accepts); + if (localVarAccept != null) localVarRequestOptions.HeaderParameters.Add("Accept", localVarAccept); + + + // authentication (OAuth2PasswordBearer) required + // oauth required + if (!string.IsNullOrEmpty(this.Configuration.AccessToken) && !localVarRequestOptions.HeaderParameters.ContainsKey("Authorization")) + { + localVarRequestOptions.HeaderParameters.Add("Authorization", "Bearer " + this.Configuration.AccessToken); + } + + // make the HTTP request + var localVarResponse = this.Client.Get("/users/me/devicecode", localVarRequestOptions, this.Configuration); + + if (this.ExceptionFactory != null) + { + Exception _exception = this.ExceptionFactory("GetUsersDeviceCodeUsersMeDevicecodeGet", localVarResponse); + if (_exception != null) throw _exception; + } + + return localVarResponse; + } + + /// + /// Get Users Device Code + /// + /// Thrown when fails to make API call + /// Cancellation Token to cancel the request. + /// Task of DeviceCode + public async System.Threading.Tasks.Task GetUsersDeviceCodeUsersMeDevicecodeGetAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + var task = GetUsersDeviceCodeUsersMeDevicecodeGetWithHttpInfoAsync(cancellationToken); +#if UNITY_EDITOR || !UNITY_WEBGL + Org.OpenAPITools.Client.ApiResponse localVarResponse = await task.ConfigureAwait(false); +#else + Org.OpenAPITools.Client.ApiResponse localVarResponse = await task; +#endif + return localVarResponse.Data; + } + + /// + /// Get Users Device Code + /// + /// Thrown when fails to make API call + /// Cancellation Token to cancel the request. + /// Task of ApiResponse (DeviceCode) + public async System.Threading.Tasks.Task> GetUsersDeviceCodeUsersMeDevicecodeGetWithHttpInfoAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + + Org.OpenAPITools.Client.RequestOptions localVarRequestOptions = new Org.OpenAPITools.Client.RequestOptions(); + + string[] _contentTypes = new string[] { + }; + + // to determine the Accept header + string[] _accepts = new string[] { + "application/json" + }; + + + var localVarContentType = Org.OpenAPITools.Client.ClientUtils.SelectHeaderContentType(_contentTypes); + if (localVarContentType != null) localVarRequestOptions.HeaderParameters.Add("Content-Type", localVarContentType); + + var localVarAccept = Org.OpenAPITools.Client.ClientUtils.SelectHeaderAccept(_accepts); + if (localVarAccept != null) localVarRequestOptions.HeaderParameters.Add("Accept", localVarAccept); + + + // authentication (OAuth2PasswordBearer) required + // oauth required + if (!string.IsNullOrEmpty(this.Configuration.AccessToken) && !localVarRequestOptions.HeaderParameters.ContainsKey("Authorization")) + { + localVarRequestOptions.HeaderParameters.Add("Authorization", "Bearer " + this.Configuration.AccessToken); + } + + // make the HTTP request + + var task = this.AsynchronousClient.GetAsync("/users/me/devicecode", localVarRequestOptions, this.Configuration, cancellationToken); + +#if UNITY_EDITOR || !UNITY_WEBGL + var localVarResponse = await task.ConfigureAwait(false); +#else + var localVarResponse = await task; +#endif + + if (this.ExceptionFactory != null) + { + Exception _exception = this.ExceptionFactory("GetUsersDeviceCodeUsersMeDevicecodeGet", localVarResponse); + if (_exception != null) throw _exception; + } + + return localVarResponse; + } + + /// + /// Get Users Me + /// + /// Thrown when fails to make API call + /// FullUser + public FullUser GetUsersMeUsersMeGet() + { + Org.OpenAPITools.Client.ApiResponse localVarResponse = GetUsersMeUsersMeGetWithHttpInfo(); + return localVarResponse.Data; + } + + /// + /// Get Users Me + /// + /// Thrown when fails to make API call + /// ApiResponse of FullUser + public Org.OpenAPITools.Client.ApiResponse GetUsersMeUsersMeGetWithHttpInfo() + { + Org.OpenAPITools.Client.RequestOptions localVarRequestOptions = new Org.OpenAPITools.Client.RequestOptions(); + + string[] _contentTypes = new string[] { + }; + + // to determine the Accept header + string[] _accepts = new string[] { + "application/json" + }; + + var localVarContentType = Org.OpenAPITools.Client.ClientUtils.SelectHeaderContentType(_contentTypes); + if (localVarContentType != null) localVarRequestOptions.HeaderParameters.Add("Content-Type", localVarContentType); + + var localVarAccept = Org.OpenAPITools.Client.ClientUtils.SelectHeaderAccept(_accepts); + if (localVarAccept != null) localVarRequestOptions.HeaderParameters.Add("Accept", localVarAccept); + + + // authentication (OAuth2PasswordBearer) required + // oauth required + if (!string.IsNullOrEmpty(this.Configuration.AccessToken) && !localVarRequestOptions.HeaderParameters.ContainsKey("Authorization")) + { + localVarRequestOptions.HeaderParameters.Add("Authorization", "Bearer " + this.Configuration.AccessToken); + } + + // make the HTTP request + var localVarResponse = this.Client.Get("/users/me", localVarRequestOptions, this.Configuration); + + if (this.ExceptionFactory != null) + { + Exception _exception = this.ExceptionFactory("GetUsersMeUsersMeGet", localVarResponse); + if (_exception != null) throw _exception; + } + + return localVarResponse; + } + + /// + /// Get Users Me + /// + /// Thrown when fails to make API call + /// Cancellation Token to cancel the request. + /// Task of FullUser + public async System.Threading.Tasks.Task GetUsersMeUsersMeGetAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + var task = GetUsersMeUsersMeGetWithHttpInfoAsync(cancellationToken); +#if UNITY_EDITOR || !UNITY_WEBGL + Org.OpenAPITools.Client.ApiResponse localVarResponse = await task.ConfigureAwait(false); +#else + Org.OpenAPITools.Client.ApiResponse localVarResponse = await task; +#endif + return localVarResponse.Data; + } + + /// + /// Get Users Me + /// + /// Thrown when fails to make API call + /// Cancellation Token to cancel the request. + /// Task of ApiResponse (FullUser) + public async System.Threading.Tasks.Task> GetUsersMeUsersMeGetWithHttpInfoAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + + Org.OpenAPITools.Client.RequestOptions localVarRequestOptions = new Org.OpenAPITools.Client.RequestOptions(); + + string[] _contentTypes = new string[] { + }; + + // to determine the Accept header + string[] _accepts = new string[] { + "application/json" + }; + + + var localVarContentType = Org.OpenAPITools.Client.ClientUtils.SelectHeaderContentType(_contentTypes); + if (localVarContentType != null) localVarRequestOptions.HeaderParameters.Add("Content-Type", localVarContentType); + + var localVarAccept = Org.OpenAPITools.Client.ClientUtils.SelectHeaderAccept(_accepts); + if (localVarAccept != null) localVarRequestOptions.HeaderParameters.Add("Accept", localVarAccept); + + + // authentication (OAuth2PasswordBearer) required + // oauth required + if (!string.IsNullOrEmpty(this.Configuration.AccessToken) && !localVarRequestOptions.HeaderParameters.ContainsKey("Authorization")) + { + localVarRequestOptions.HeaderParameters.Add("Authorization", "Bearer " + this.Configuration.AccessToken); + } + + // make the HTTP request + + var task = this.AsynchronousClient.GetAsync("/users/me", localVarRequestOptions, this.Configuration, cancellationToken); + +#if UNITY_EDITOR || !UNITY_WEBGL + var localVarResponse = await task.ConfigureAwait(false); +#else + var localVarResponse = await task; +#endif + + if (this.ExceptionFactory != null) + { + Exception _exception = this.ExceptionFactory("GetUsersMeUsersMeGet", localVarResponse); + if (_exception != null) throw _exception; + } + + return localVarResponse; + } + + /// + /// Update User + /// + /// Thrown when fails to make API call + /// + /// FullUser + public FullUser UpdateUserUsersMePatch(PatchUser patchUser) + { + Org.OpenAPITools.Client.ApiResponse localVarResponse = UpdateUserUsersMePatchWithHttpInfo(patchUser); + return localVarResponse.Data; + } + + /// + /// Update User + /// + /// Thrown when fails to make API call + /// + /// ApiResponse of FullUser + public Org.OpenAPITools.Client.ApiResponse UpdateUserUsersMePatchWithHttpInfo(PatchUser patchUser) + { + // verify the required parameter 'patchUser' is set + if (patchUser == null) + throw new Org.OpenAPITools.Client.ApiException(400, "Missing required parameter 'patchUser' when calling UsersApi->UpdateUserUsersMePatch"); + + Org.OpenAPITools.Client.RequestOptions localVarRequestOptions = new Org.OpenAPITools.Client.RequestOptions(); + + string[] _contentTypes = new string[] { + "application/json" + }; + + // to determine the Accept header + string[] _accepts = new string[] { + "application/json" + }; + + var localVarContentType = Org.OpenAPITools.Client.ClientUtils.SelectHeaderContentType(_contentTypes); + if (localVarContentType != null) localVarRequestOptions.HeaderParameters.Add("Content-Type", localVarContentType); + + var localVarAccept = Org.OpenAPITools.Client.ClientUtils.SelectHeaderAccept(_accepts); + if (localVarAccept != null) localVarRequestOptions.HeaderParameters.Add("Accept", localVarAccept); + + localVarRequestOptions.Data = patchUser; + + // authentication (OAuth2PasswordBearer) required + // oauth required + if (!string.IsNullOrEmpty(this.Configuration.AccessToken) && !localVarRequestOptions.HeaderParameters.ContainsKey("Authorization")) + { + localVarRequestOptions.HeaderParameters.Add("Authorization", "Bearer " + this.Configuration.AccessToken); + } + + // make the HTTP request + var localVarResponse = this.Client.Patch("/users/me", localVarRequestOptions, this.Configuration); + + if (this.ExceptionFactory != null) + { + Exception _exception = this.ExceptionFactory("UpdateUserUsersMePatch", localVarResponse); + if (_exception != null) throw _exception; + } + + return localVarResponse; + } + + /// + /// Update User + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of FullUser + public async System.Threading.Tasks.Task UpdateUserUsersMePatchAsync(PatchUser patchUser, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + var task = UpdateUserUsersMePatchWithHttpInfoAsync(patchUser, cancellationToken); +#if UNITY_EDITOR || !UNITY_WEBGL + Org.OpenAPITools.Client.ApiResponse localVarResponse = await task.ConfigureAwait(false); +#else + Org.OpenAPITools.Client.ApiResponse localVarResponse = await task; +#endif + return localVarResponse.Data; + } + + /// + /// Update User + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of ApiResponse (FullUser) + public async System.Threading.Tasks.Task> UpdateUserUsersMePatchWithHttpInfoAsync(PatchUser patchUser, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + // verify the required parameter 'patchUser' is set + if (patchUser == null) + throw new Org.OpenAPITools.Client.ApiException(400, "Missing required parameter 'patchUser' when calling UsersApi->UpdateUserUsersMePatch"); + + + Org.OpenAPITools.Client.RequestOptions localVarRequestOptions = new Org.OpenAPITools.Client.RequestOptions(); + + string[] _contentTypes = new string[] { + "application/json" + }; + + // to determine the Accept header + string[] _accepts = new string[] { + "application/json" + }; + + + var localVarContentType = Org.OpenAPITools.Client.ClientUtils.SelectHeaderContentType(_contentTypes); + if (localVarContentType != null) localVarRequestOptions.HeaderParameters.Add("Content-Type", localVarContentType); + + var localVarAccept = Org.OpenAPITools.Client.ClientUtils.SelectHeaderAccept(_accepts); + if (localVarAccept != null) localVarRequestOptions.HeaderParameters.Add("Accept", localVarAccept); + + localVarRequestOptions.Data = patchUser; + + // authentication (OAuth2PasswordBearer) required + // oauth required + if (!string.IsNullOrEmpty(this.Configuration.AccessToken) && !localVarRequestOptions.HeaderParameters.ContainsKey("Authorization")) + { + localVarRequestOptions.HeaderParameters.Add("Authorization", "Bearer " + this.Configuration.AccessToken); + } + + // make the HTTP request + + var task = this.AsynchronousClient.PatchAsync("/users/me", localVarRequestOptions, this.Configuration, cancellationToken); + +#if UNITY_EDITOR || !UNITY_WEBGL + var localVarResponse = await task.ConfigureAwait(false); +#else + var localVarResponse = await task; +#endif + + if (this.ExceptionFactory != null) + { + Exception _exception = this.ExceptionFactory("UpdateUserUsersMePatch", localVarResponse); + if (_exception != null) throw _exception; + } + + return localVarResponse; + } + + /// + /// User Password Reset Request + /// + /// Thrown when fails to make API call + /// + /// Object + public Object UserPasswordResetRequestUsersPasswordResetPut(PasswordReset passwordReset) + { + Org.OpenAPITools.Client.ApiResponse localVarResponse = UserPasswordResetRequestUsersPasswordResetPutWithHttpInfo(passwordReset); + return localVarResponse.Data; + } + + /// + /// User Password Reset Request + /// + /// Thrown when fails to make API call + /// + /// ApiResponse of Object + public Org.OpenAPITools.Client.ApiResponse UserPasswordResetRequestUsersPasswordResetPutWithHttpInfo(PasswordReset passwordReset) + { + // verify the required parameter 'passwordReset' is set + if (passwordReset == null) + throw new Org.OpenAPITools.Client.ApiException(400, "Missing required parameter 'passwordReset' when calling UsersApi->UserPasswordResetRequestUsersPasswordResetPut"); + + Org.OpenAPITools.Client.RequestOptions localVarRequestOptions = new Org.OpenAPITools.Client.RequestOptions(); + + string[] _contentTypes = new string[] { + "application/json" + }; + + // to determine the Accept header + string[] _accepts = new string[] { + "application/json" + }; + + var localVarContentType = Org.OpenAPITools.Client.ClientUtils.SelectHeaderContentType(_contentTypes); + if (localVarContentType != null) localVarRequestOptions.HeaderParameters.Add("Content-Type", localVarContentType); + + var localVarAccept = Org.OpenAPITools.Client.ClientUtils.SelectHeaderAccept(_accepts); + if (localVarAccept != null) localVarRequestOptions.HeaderParameters.Add("Accept", localVarAccept); + + localVarRequestOptions.Data = passwordReset; + + + // make the HTTP request + var localVarResponse = this.Client.Put("/users/password/reset", localVarRequestOptions, this.Configuration); + + if (this.ExceptionFactory != null) + { + Exception _exception = this.ExceptionFactory("UserPasswordResetRequestUsersPasswordResetPut", localVarResponse); + if (_exception != null) throw _exception; + } + + return localVarResponse; + } + + /// + /// User Password Reset Request + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of Object + public async System.Threading.Tasks.Task UserPasswordResetRequestUsersPasswordResetPutAsync(PasswordReset passwordReset, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + var task = UserPasswordResetRequestUsersPasswordResetPutWithHttpInfoAsync(passwordReset, cancellationToken); +#if UNITY_EDITOR || !UNITY_WEBGL + Org.OpenAPITools.Client.ApiResponse localVarResponse = await task.ConfigureAwait(false); +#else + Org.OpenAPITools.Client.ApiResponse localVarResponse = await task; +#endif + return localVarResponse.Data; + } + + /// + /// User Password Reset Request + /// + /// Thrown when fails to make API call + /// + /// Cancellation Token to cancel the request. + /// Task of ApiResponse (Object) + public async System.Threading.Tasks.Task> UserPasswordResetRequestUsersPasswordResetPutWithHttpInfoAsync(PasswordReset passwordReset, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + // verify the required parameter 'passwordReset' is set + if (passwordReset == null) + throw new Org.OpenAPITools.Client.ApiException(400, "Missing required parameter 'passwordReset' when calling UsersApi->UserPasswordResetRequestUsersPasswordResetPut"); + + + Org.OpenAPITools.Client.RequestOptions localVarRequestOptions = new Org.OpenAPITools.Client.RequestOptions(); + + string[] _contentTypes = new string[] { + "application/json" + }; + + // to determine the Accept header + string[] _accepts = new string[] { + "application/json" + }; + + + var localVarContentType = Org.OpenAPITools.Client.ClientUtils.SelectHeaderContentType(_contentTypes); + if (localVarContentType != null) localVarRequestOptions.HeaderParameters.Add("Content-Type", localVarContentType); + + var localVarAccept = Org.OpenAPITools.Client.ClientUtils.SelectHeaderAccept(_accepts); + if (localVarAccept != null) localVarRequestOptions.HeaderParameters.Add("Accept", localVarAccept); + + localVarRequestOptions.Data = passwordReset; + + + // make the HTTP request + + var task = this.AsynchronousClient.PutAsync("/users/password/reset", localVarRequestOptions, this.Configuration, cancellationToken); + +#if UNITY_EDITOR || !UNITY_WEBGL + var localVarResponse = await task.ConfigureAwait(false); +#else + var localVarResponse = await task; +#endif + + if (this.ExceptionFactory != null) + { + Exception _exception = this.ExceptionFactory("UserPasswordResetRequestUsersPasswordResetPut", localVarResponse); + if (_exception != null) throw _exception; + } + + return localVarResponse; + } + + } +} diff --git a/Assets/ThirdParty/Org.OpenAPITools/Api/UsersApi.cs.meta b/Assets/ThirdParty/Org.OpenAPITools/Api/UsersApi.cs.meta new file mode 100644 index 0000000000..3a1a2439da --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Api/UsersApi.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bb0a24d64c62a4b1a8977646b70307a9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThirdParty/Org.OpenAPITools/Client.meta b/Assets/ThirdParty/Org.OpenAPITools/Client.meta new file mode 100644 index 0000000000..b3e42bb7ac --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Client.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 36bb7bbc9cde448ebbdbfc9144981c11 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThirdParty/Org.OpenAPITools/Client/ApiClient.cs b/Assets/ThirdParty/Org.OpenAPITools/Client/ApiClient.cs new file mode 100644 index 0000000000..e29296628c --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Client/ApiClient.cs @@ -0,0 +1,645 @@ +/* + * Icosa API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 0.1.0 + * Generated by: https://github.com/openapitools/openapi-generator.git + */ + + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Net; +using System.Reflection; +using System.Runtime.Serialization; +using System.Runtime.Serialization.Formatters; +using System.Text; +using System.Threading; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using Newtonsoft.Json; +using Newtonsoft.Json.Serialization; +using ErrorEventArgs = Newtonsoft.Json.Serialization.ErrorEventArgs; +using System.Net.Http; +using System.Net.Http.Headers; +using UnityEngine.Networking; +using UnityEngine; + +namespace Org.OpenAPITools.Client +{ + /// + /// To Serialize/Deserialize JSON using our custom logic, but only when ContentType is JSON. + /// + internal class CustomJsonCodec + { + private readonly IReadableConfiguration _configuration; + private static readonly string _contentType = "application/json"; + private readonly JsonSerializerSettings _serializerSettings = new JsonSerializerSettings + { + // OpenAPI generated types generally hide default constructors. + ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor, + ContractResolver = new DefaultContractResolver + { + NamingStrategy = new CamelCaseNamingStrategy + { + OverrideSpecifiedNames = false + } + } + }; + + public CustomJsonCodec(IReadableConfiguration configuration) + { + _configuration = configuration; + } + + public CustomJsonCodec(JsonSerializerSettings serializerSettings, IReadableConfiguration configuration) + { + _serializerSettings = serializerSettings; + _configuration = configuration; + } + + /// + /// Serialize the object into a JSON string. + /// + /// Object to be serialized. + /// A JSON string. + public string Serialize(object obj) + { + if (obj != null && obj is Org.OpenAPITools.Model.AbstractOpenAPISchema) + { + // the object to be serialized is an oneOf/anyOf schema + return ((Org.OpenAPITools.Model.AbstractOpenAPISchema)obj).ToJson(); + } + else + { + return JsonConvert.SerializeObject(obj, _serializerSettings); + } + } + + public T Deserialize(UnityWebRequest request) + { + var result = (T) Deserialize(request, typeof(T)); + return result; + } + + /// + /// Deserialize the JSON string into a proper object. + /// + /// The UnityWebRequest after it has a response. + /// Object type. + /// Object representation of the JSON string. + internal object Deserialize(UnityWebRequest request, Type type) + { + if (type == typeof(byte[])) // return byte array + { + return request.downloadHandler.data; + } + + // TODO: ? if (type.IsAssignableFrom(typeof(Stream))) + if (type == typeof(Stream)) + { + // NOTE: Ignoring Content-Disposition filename support, since not all platforms + // have a location on disk to write arbitrary data (tvOS, consoles). + return new MemoryStream(request.downloadHandler.data); + } + + if (type.Name.StartsWith("System.Nullable`1[[System.DateTime")) // return a datetime object + { + return DateTime.Parse(request.downloadHandler.text, null, System.Globalization.DateTimeStyles.RoundtripKind); + } + + if (type == typeof(string) || type.Name.StartsWith("System.Nullable")) // return primitive type + { + return Convert.ChangeType(request.downloadHandler.text, type); + } + + var contentType = request.GetResponseHeader("Content-Type"); + + if (!string.IsNullOrEmpty(contentType) && contentType.Contains("application/json")) + { + var text = request.downloadHandler?.text; + + // Generated APIs that don't expect a return value provide System.Object as the type + if (type == typeof(System.Object) && (string.IsNullOrEmpty(text) || text.Trim() == "null")) + { + return null; + } + + if (request.responseCode >= 200 && request.responseCode < 300) + { + try + { + // Deserialize as a model + return JsonConvert.DeserializeObject(text, type, _serializerSettings); + } + catch (Exception e) + { + throw new UnexpectedResponseException(request, type, e.ToString()); + } + } + else + { + throw new ApiException((int)request.responseCode, request.error, text); + } + } + + if (type != typeof(System.Object) && request.responseCode >= 200 && request.responseCode < 300) + { + throw new UnexpectedResponseException(request, type); + } + + return null; + + } + + public string RootElement { get; set; } + public string Namespace { get; set; } + public string DateFormat { get; set; } + + public string ContentType + { + get { return _contentType; } + set { throw new InvalidOperationException("Not allowed to set content type."); } + } + } + /// + /// Provides a default implementation of an Api client (both synchronous and asynchronous implementations), + /// encapsulating general REST accessor use cases. + /// + /// + /// The Dispose method will manage the HttpClient lifecycle when not passed by constructor. + /// + public partial class ApiClient : IDisposable, ISynchronousClient, IAsynchronousClient + { + private readonly string _baseUrl; + + /// + /// Specifies the settings on a object. + /// These settings can be adjusted to accommodate custom serialization rules. + /// + public JsonSerializerSettings SerializerSettings { get; set; } = new JsonSerializerSettings + { + // OpenAPI generated types generally hide default constructors. + ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor, + ContractResolver = new DefaultContractResolver + { + NamingStrategy = new CamelCaseNamingStrategy + { + OverrideSpecifiedNames = false + } + } + }; + + /// + /// Initializes a new instance of the , defaulting to the global configurations' base url. + /// + public ApiClient() : + this(Org.OpenAPITools.Client.GlobalConfiguration.Instance.BasePath) + { + } + + /// + /// Initializes a new instance of the . + /// + /// The target service's base path in URL format. + /// + public ApiClient(string basePath) + { + if (string.IsNullOrEmpty(basePath)) throw new ArgumentException("basePath cannot be empty"); + + _baseUrl = basePath; + } + + /// + /// Disposes resources if they were created by us + /// + public void Dispose() + { + } + + /// + /// Provides all logic for constructing a new UnityWebRequest. + /// At this point, all information for querying the service is known. Here, it is simply + /// mapped into the UnityWebRequest. + /// + /// The http verb. + /// The target path (or resource). + /// The additional request options. + /// A per-request configuration object. It is assumed that any merge with + /// GlobalConfiguration has been done before calling this method. + /// [private] A new UnityWebRequest instance. + /// + private UnityWebRequest NewRequest( + string method, + string path, + RequestOptions options, + IReadableConfiguration configuration) + { + if (path == null) throw new ArgumentNullException("path"); + if (options == null) throw new ArgumentNullException("options"); + if (configuration == null) throw new ArgumentNullException("configuration"); + + WebRequestPathBuilder builder = new WebRequestPathBuilder(_baseUrl, path); + + builder.AddPathParameters(options.PathParameters); + + builder.AddQueryParameters(options.QueryParameters); + + string contentType = null; + if (options.HeaderParameters != null && options.HeaderParameters.ContainsKey("Content-Type")) + { + var contentTypes = options.HeaderParameters["Content-Type"]; + contentType = contentTypes.FirstOrDefault(); + } + + var uri = builder.GetFullUri(); + UnityWebRequest request = null; + + if (contentType == "multipart/form-data") + { + var formData = new List(); + foreach (var formParameter in options.FormParameters) + { + formData.Add(new MultipartFormDataSection(formParameter.Key, formParameter.Value)); + } + + request = UnityWebRequest.Post(uri, formData); + request.method = method; + } + else if (contentType == "application/x-www-form-urlencoded") + { + var form = new WWWForm(); + foreach (var kvp in options.FormParameters) + { + form.AddField(kvp.Key, kvp.Value); + } + + request = UnityWebRequest.Post(uri, form); + request.method = method; + } + else if (options.Data != null) + { + var serializer = new CustomJsonCodec(SerializerSettings, configuration); + var jsonData = serializer.Serialize(options.Data); + + // Making a post body application/json encoded is whack with UnityWebRequest. + // See: https://stackoverflow.com/questions/68156230/unitywebrequest-post-not-sending-body + request = UnityWebRequest.Put(uri, jsonData); + request.method = method; + request.SetRequestHeader("Content-Type", "application/json"); + } + else + { + request = new UnityWebRequest(builder.GetFullUri(), method); + } + + if (request.downloadHandler == null && typeof(T) != typeof(System.Object)) + { + request.downloadHandler = new DownloadHandlerBuffer(); + } + +#if UNITY_EDITOR || !UNITY_WEBGL + if (configuration.UserAgent != null) + { + request.SetRequestHeader("User-Agent", configuration.UserAgent); + } +#endif + + if (configuration.DefaultHeaders != null) + { + foreach (var headerParam in configuration.DefaultHeaders) + { + request.SetRequestHeader(headerParam.Key, headerParam.Value); + } + } + + if (options.HeaderParameters != null) + { + foreach (var headerParam in options.HeaderParameters) + { + foreach (var value in headerParam.Value) + { + // Todo make content headers actually content headers + request.SetRequestHeader(headerParam.Key, value); + } + } + } + + if (options.Cookies != null && options.Cookies.Count > 0) + { + #if UNITY_WEBGL + throw new System.InvalidOperationException("UnityWebRequest does not support setting cookies in WebGL"); + #else + if (options.Cookies.Count != 1) + { + UnityEngine.Debug.LogError("Only one cookie supported, ignoring others"); + } + + request.SetRequestHeader("Cookie", options.Cookies[0].ToString()); + #endif + } + + return request; + + } + + partial void InterceptRequest(UnityWebRequest req, string path, RequestOptions options, IReadableConfiguration configuration); + partial void InterceptResponse(UnityWebRequest req, string path, RequestOptions options, IReadableConfiguration configuration, ref object responseData); + + private ApiResponse ToApiResponse(UnityWebRequest request, object responseData) + { + T result = (T) responseData; + + var transformed = new ApiResponse((HttpStatusCode)request.responseCode, new Multimap(), result, request.downloadHandler?.text ?? "") + { + ErrorText = request.error, + Cookies = new List() + }; + + // process response headers, e.g. Access-Control-Allow-Methods + var responseHeaders = request.GetResponseHeaders(); + if (responseHeaders != null) + { + foreach (var responseHeader in request.GetResponseHeaders()) + { + transformed.Headers.Add(responseHeader.Key, ClientUtils.ParameterToString(responseHeader.Value)); + } + } + + return transformed; + } + + private async Task> ExecAsync( + UnityWebRequest request, + string path, + RequestOptions options, + IReadableConfiguration configuration, + System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + var deserializer = new CustomJsonCodec(SerializerSettings, configuration); + + using (request) + { + if (configuration.Timeout > 0) + { + request.timeout = (int)Math.Ceiling(configuration.Timeout / 1000.0f); + } + + if (configuration.Proxy != null) + { + throw new InvalidOperationException("Configuration `Proxy` not supported by UnityWebRequest"); + } + + if (configuration.ClientCertificates != null) + { + // Only Android/iOS/tvOS/Standalone players can support certificates, and this + // implementation is intended to work on all platforms. + // + // TODO: Could optionally allow support for this on these platforms. + // + // See: https://docs.unity3d.com/ScriptReference/Networking.CertificateHandler.html + throw new InvalidOperationException("Configuration `ClientCertificates` not supported by UnityWebRequest on all platforms"); + } + + InterceptRequest(request, path, options, configuration); + + var asyncOp = request.SendWebRequest(); + + TaskCompletionSource tsc = new TaskCompletionSource(); + asyncOp.completed += (_) => tsc.TrySetResult(request.result); + + using (var tokenRegistration = cancellationToken.Register(request.Abort, true)) + { + await tsc.Task; + } + + if (request.result == UnityWebRequest.Result.ConnectionError || + request.result == UnityWebRequest.Result.DataProcessingError) + { + throw new ConnectionException(request); + } + + object responseData = deserializer.Deserialize(request); + + // if the response type is oneOf/anyOf, call FromJSON to deserialize the data + if (typeof(Org.OpenAPITools.Model.AbstractOpenAPISchema).IsAssignableFrom(typeof(T))) + { + responseData = (T) typeof(T).GetMethod("FromJson").Invoke(null, new object[] { new ByteArrayContent(request.downloadHandler.data) }); + } + else if (typeof(T).Name == "Stream") // for binary response + { + responseData = (T) (object) new MemoryStream(request.downloadHandler.data); + } + + InterceptResponse(request, path, options, configuration, ref responseData); + + return ToApiResponse(request, responseData); + } + } + + #region IAsynchronousClient + /// + /// Make a HTTP GET request (async). + /// + /// The target path (or resource). + /// The additional request options. + /// A per-request configuration object. It is assumed that any merge with + /// GlobalConfiguration has been done before calling this method. + /// Token that enables callers to cancel the request. + /// A Task containing ApiResponse + public Task> GetAsync(string path, RequestOptions options, IReadableConfiguration configuration = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + var config = configuration ?? GlobalConfiguration.Instance; + return ExecAsync(NewRequest("GET", path, options, config), path, options, config, cancellationToken); + } + + /// + /// Make a HTTP POST request (async). + /// + /// The target path (or resource). + /// The additional request options. + /// A per-request configuration object. It is assumed that any merge with + /// GlobalConfiguration has been done before calling this method. + /// Token that enables callers to cancel the request. + /// A Task containing ApiResponse + public Task> PostAsync(string path, RequestOptions options, IReadableConfiguration configuration = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + var config = configuration ?? GlobalConfiguration.Instance; + return ExecAsync(NewRequest("POST", path, options, config), path, options, config, cancellationToken); + } + + /// + /// Make a HTTP PUT request (async). + /// + /// The target path (or resource). + /// The additional request options. + /// A per-request configuration object. It is assumed that any merge with + /// GlobalConfiguration has been done before calling this method. + /// Token that enables callers to cancel the request. + /// A Task containing ApiResponse + public Task> PutAsync(string path, RequestOptions options, IReadableConfiguration configuration = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + var config = configuration ?? GlobalConfiguration.Instance; + return ExecAsync(NewRequest("PUT", path, options, config), path, options, config, cancellationToken); + } + + /// + /// Make a HTTP DELETE request (async). + /// + /// The target path (or resource). + /// The additional request options. + /// A per-request configuration object. It is assumed that any merge with + /// GlobalConfiguration has been done before calling this method. + /// Token that enables callers to cancel the request. + /// A Task containing ApiResponse + public Task> DeleteAsync(string path, RequestOptions options, IReadableConfiguration configuration = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + var config = configuration ?? GlobalConfiguration.Instance; + return ExecAsync(NewRequest("DELETE", path, options, config), path, options, config, cancellationToken); + } + + /// + /// Make a HTTP HEAD request (async). + /// + /// The target path (or resource). + /// The additional request options. + /// A per-request configuration object. It is assumed that any merge with + /// GlobalConfiguration has been done before calling this method. + /// Token that enables callers to cancel the request. + /// A Task containing ApiResponse + public Task> HeadAsync(string path, RequestOptions options, IReadableConfiguration configuration = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + var config = configuration ?? GlobalConfiguration.Instance; + return ExecAsync(NewRequest("HEAD", path, options, config), path, options, config, cancellationToken); + } + + /// + /// Make a HTTP OPTION request (async). + /// + /// The target path (or resource). + /// The additional request options. + /// A per-request configuration object. It is assumed that any merge with + /// GlobalConfiguration has been done before calling this method. + /// Token that enables callers to cancel the request. + /// A Task containing ApiResponse + public Task> OptionsAsync(string path, RequestOptions options, IReadableConfiguration configuration = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + var config = configuration ?? GlobalConfiguration.Instance; + return ExecAsync(NewRequest("OPTIONS", path, options, config), path, options, config, cancellationToken); + } + + /// + /// Make a HTTP PATCH request (async). + /// + /// The target path (or resource). + /// The additional request options. + /// A per-request configuration object. It is assumed that any merge with + /// GlobalConfiguration has been done before calling this method. + /// Token that enables callers to cancel the request. + /// A Task containing ApiResponse + public Task> PatchAsync(string path, RequestOptions options, IReadableConfiguration configuration = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) + { + var config = configuration ?? GlobalConfiguration.Instance; + return ExecAsync(NewRequest("PATCH", path, options, config), path, options, config, cancellationToken); + } + #endregion IAsynchronousClient + + #region ISynchronousClient + /// + /// Make a HTTP GET request (synchronous). + /// + /// The target path (or resource). + /// The additional request options. + /// A per-request configuration object. It is assumed that any merge with + /// GlobalConfiguration has been done before calling this method. + /// A Task containing ApiResponse + public ApiResponse Get(string path, RequestOptions options, IReadableConfiguration configuration = null) + { + throw new System.NotImplementedException("UnityWebRequest does not support synchronous operation"); + } + + /// + /// Make a HTTP POST request (synchronous). + /// + /// The target path (or resource). + /// The additional request options. + /// A per-request configuration object. It is assumed that any merge with + /// GlobalConfiguration has been done before calling this method. + /// A Task containing ApiResponse + public ApiResponse Post(string path, RequestOptions options, IReadableConfiguration configuration = null) + { + throw new System.NotImplementedException("UnityWebRequest does not support synchronous operation"); + } + + /// + /// Make a HTTP PUT request (synchronous). + /// + /// The target path (or resource). + /// The additional request options. + /// A per-request configuration object. It is assumed that any merge with + /// GlobalConfiguration has been done before calling this method. + /// A Task containing ApiResponse + public ApiResponse Put(string path, RequestOptions options, IReadableConfiguration configuration = null) + { + throw new System.NotImplementedException("UnityWebRequest does not support synchronous operation"); + } + + /// + /// Make a HTTP DELETE request (synchronous). + /// + /// The target path (or resource). + /// The additional request options. + /// A per-request configuration object. It is assumed that any merge with + /// GlobalConfiguration has been done before calling this method. + /// A Task containing ApiResponse + public ApiResponse Delete(string path, RequestOptions options, IReadableConfiguration configuration = null) + { + throw new System.NotImplementedException("UnityWebRequest does not support synchronous operation"); + } + + /// + /// Make a HTTP HEAD request (synchronous). + /// + /// The target path (or resource). + /// The additional request options. + /// A per-request configuration object. It is assumed that any merge with + /// GlobalConfiguration has been done before calling this method. + /// A Task containing ApiResponse + public ApiResponse Head(string path, RequestOptions options, IReadableConfiguration configuration = null) + { + throw new System.NotImplementedException("UnityWebRequest does not support synchronous operation"); + } + + /// + /// Make a HTTP OPTION request (synchronous). + /// + /// The target path (or resource). + /// The additional request options. + /// A per-request configuration object. It is assumed that any merge with + /// GlobalConfiguration has been done before calling this method. + /// A Task containing ApiResponse + public ApiResponse Options(string path, RequestOptions options, IReadableConfiguration configuration = null) + { + throw new System.NotImplementedException("UnityWebRequest does not support synchronous operation"); + } + + /// + /// Make a HTTP PATCH request (synchronous). + /// + /// The target path (or resource). + /// The additional request options. + /// A per-request configuration object. It is assumed that any merge with + /// GlobalConfiguration has been done before calling this method. + /// A Task containing ApiResponse + public ApiResponse Patch(string path, RequestOptions options, IReadableConfiguration configuration = null) + { + throw new System.NotImplementedException("UnityWebRequest does not support synchronous operation"); + } + #endregion ISynchronousClient + } +} \ No newline at end of file diff --git a/Assets/ThirdParty/Org.OpenAPITools/Client/ApiClient.cs.meta b/Assets/ThirdParty/Org.OpenAPITools/Client/ApiClient.cs.meta new file mode 100644 index 0000000000..57805be2b4 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Client/ApiClient.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8c2f337c5e6cb496c9cceab040961c2c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThirdParty/Org.OpenAPITools/Client/ApiException.cs b/Assets/ThirdParty/Org.OpenAPITools/Client/ApiException.cs new file mode 100644 index 0000000000..c8b51141aa --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Client/ApiException.cs @@ -0,0 +1,68 @@ +/* + * Icosa API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 0.1.0 + * Generated by: https://github.com/openapitools/openapi-generator.git + */ + + +using System; + +namespace Org.OpenAPITools.Client +{ + /// + /// API Exception + /// + public class ApiException : Exception + { + /// + /// Gets or sets the error code (HTTP status code) + /// + /// The error code (HTTP status code). + public int ErrorCode { get; set; } + + /// + /// Gets or sets the error content (body json object) + /// + /// The error content (Http response body). + public object ErrorContent { get; private set; } + + /// + /// Gets or sets the HTTP headers + /// + /// HTTP headers + public Multimap Headers { get; private set; } + + /// + /// Initializes a new instance of the class. + /// + public ApiException() { } + + /// + /// Initializes a new instance of the class. + /// + /// HTTP status code. + /// Error message. + public ApiException(int errorCode, string message) : base(message) + { + this.ErrorCode = errorCode; + } + + /// + /// Initializes a new instance of the class. + /// + /// HTTP status code. + /// Error message. + /// Error content. + /// HTTP Headers. + public ApiException(int errorCode, string message, object errorContent = null, Multimap headers = null) : base(message) + { + this.ErrorCode = errorCode; + this.ErrorContent = errorContent; + this.Headers = headers; + } + } + +} diff --git a/Assets/ThirdParty/Org.OpenAPITools/Client/ApiException.cs.meta b/Assets/ThirdParty/Org.OpenAPITools/Client/ApiException.cs.meta new file mode 100644 index 0000000000..7de35190ff --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Client/ApiException.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4648f176361564a7db678fd7bd415d19 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThirdParty/Org.OpenAPITools/Client/ApiResponse.cs b/Assets/ThirdParty/Org.OpenAPITools/Client/ApiResponse.cs new file mode 100644 index 0000000000..298c9ab2d8 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Client/ApiResponse.cs @@ -0,0 +1,166 @@ +/* + * Icosa API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 0.1.0 + * Generated by: https://github.com/openapitools/openapi-generator.git + */ + + +using System; +using System.Collections.Generic; +using System.Net; + +namespace Org.OpenAPITools.Client +{ + /// + /// Provides a non-generic contract for the ApiResponse wrapper. + /// + public interface IApiResponse + { + /// + /// The data type of + /// + Type ResponseType { get; } + + /// + /// The content of this response + /// + Object Content { get; } + + /// + /// Gets or sets the status code (HTTP status code) + /// + /// The status code. + HttpStatusCode StatusCode { get; } + + /// + /// Gets or sets the HTTP headers + /// + /// HTTP headers + Multimap Headers { get; } + + /// + /// Gets or sets any error text defined by the calling client. + /// + string ErrorText { get; set; } + + /// + /// Gets or sets any cookies passed along on the response. + /// + List Cookies { get; set; } + + /// + /// The raw content of this response + /// + string RawContent { get; } + } + + /// + /// API Response + /// + public class ApiResponse : IApiResponse + { + #region Properties + + /// + /// Gets or sets the status code (HTTP status code) + /// + /// The status code. + public HttpStatusCode StatusCode { get; } + + /// + /// Gets or sets the HTTP headers + /// + /// HTTP headers + public Multimap Headers { get; } + + /// + /// Gets or sets the data (parsed HTTP body) + /// + /// The data. + public T Data { get; } + + /// + /// Gets or sets any error text defined by the calling client. + /// + public string ErrorText { get; set; } + + /// + /// Gets or sets any cookies passed along on the response. + /// + public List Cookies { get; set; } + + /// + /// The content of this response + /// + public Type ResponseType + { + get { return typeof(T); } + } + + /// + /// The data type of + /// + public object Content + { + get { return Data; } + } + + /// + /// The raw content + /// + public string RawContent { get; } + + #endregion Properties + + #region Constructors + + /// + /// Initializes a new instance of the class. + /// + /// HTTP status code. + /// HTTP headers. + /// Data (parsed HTTP body) + /// Raw content. + public ApiResponse(HttpStatusCode statusCode, Multimap headers, T data, string rawContent) + { + StatusCode = statusCode; + Headers = headers; + Data = data; + RawContent = rawContent; + } + + /// + /// Initializes a new instance of the class. + /// + /// HTTP status code. + /// HTTP headers. + /// Data (parsed HTTP body) + public ApiResponse(HttpStatusCode statusCode, Multimap headers, T data) : this(statusCode, headers, data, null) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// HTTP status code. + /// Data (parsed HTTP body) + /// Raw content. + public ApiResponse(HttpStatusCode statusCode, T data, string rawContent) : this(statusCode, null, data, rawContent) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// HTTP status code. + /// Data (parsed HTTP body) + public ApiResponse(HttpStatusCode statusCode, T data) : this(statusCode, data, null) + { + } + + #endregion Constructors + } +} diff --git a/Assets/ThirdParty/Org.OpenAPITools/Client/ApiResponse.cs.meta b/Assets/ThirdParty/Org.OpenAPITools/Client/ApiResponse.cs.meta new file mode 100644 index 0000000000..4e0aa987fe --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Client/ApiResponse.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a5b445ecbd8584ea1a861556b3bbecda +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThirdParty/Org.OpenAPITools/Client/ClientUtils.cs b/Assets/ThirdParty/Org.OpenAPITools/Client/ClientUtils.cs new file mode 100644 index 0000000000..53f47f2ece --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Client/ClientUtils.cs @@ -0,0 +1,247 @@ +/* + * Icosa API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 0.1.0 + * Generated by: https://github.com/openapitools/openapi-generator.git + */ + + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Runtime.Serialization; +using System.Text; +using System.Text.RegularExpressions; + +namespace Org.OpenAPITools.Client +{ + /// + /// Utility functions providing some benefit to API client consumers. + /// + public static class ClientUtils + { + /// + /// Sanitize filename by removing the path + /// + /// Filename + /// Filename + public static string SanitizeFilename(string filename) + { + Match match = Regex.Match(filename, @".*[/\\](.*)$"); + return match.Success ? match.Groups[1].Value : filename; + } + + /// + /// Convert params to key/value pairs. + /// Use collectionFormat to properly format lists and collections. + /// + /// The swagger-supported collection format, one of: csv, tsv, ssv, pipes, multi + /// Key name. + /// Value object. + /// A multimap of keys with 1..n associated values. + public static Multimap ParameterToMultiMap(string collectionFormat, string name, object value) + { + var parameters = new Multimap(); + + if (value is ICollection collection && collectionFormat == "multi") + { + foreach (var item in collection) + { + parameters.Add(name, ParameterToString(item)); + } + } + else if (value is IDictionary dictionary) + { + if(collectionFormat == "deepObject") { + foreach (DictionaryEntry entry in dictionary) + { + parameters.Add(name + "[" + entry.Key + "]", ParameterToString(entry.Value)); + } + } + else { + foreach (DictionaryEntry entry in dictionary) + { + parameters.Add(entry.Key.ToString(), ParameterToString(entry.Value)); + } + } + } + else + { + parameters.Add(name, ParameterToString(value)); + } + + return parameters; + } + + /// + /// If parameter is DateTime, output in a formatted string (default ISO 8601), customizable with Configuration.DateTime. + /// If parameter is a list, join the list with ",". + /// Otherwise just return the string. + /// + /// The parameter (header, path, query, form). + /// An optional configuration instance, providing formatting options used in processing. + /// Formatted string. + public static string ParameterToString(object obj, IReadableConfiguration configuration = null) + { + if (obj is DateTime dateTime) + // Return a formatted date string - Can be customized with Configuration.DateTimeFormat + // Defaults to an ISO 8601, using the known as a Round-trip date/time pattern ("o") + // https://msdn.microsoft.com/en-us/library/az4se3k1(v=vs.110).aspx#Anchor_8 + // For example: 2009-06-15T13:45:30.0000000 + return dateTime.ToString((configuration ?? GlobalConfiguration.Instance).DateTimeFormat); + if (obj is DateTimeOffset dateTimeOffset) + // Return a formatted date string - Can be customized with Configuration.DateTimeFormat + // Defaults to an ISO 8601, using the known as a Round-trip date/time pattern ("o") + // https://msdn.microsoft.com/en-us/library/az4se3k1(v=vs.110).aspx#Anchor_8 + // For example: 2009-06-15T13:45:30.0000000 + return dateTimeOffset.ToString((configuration ?? GlobalConfiguration.Instance).DateTimeFormat); + if (obj is bool boolean) + return boolean ? "true" : "false"; + if (obj is ICollection collection) { + List entries = new List(); + foreach (var entry in collection) + entries.Add(ParameterToString(entry, configuration)); + return string.Join(",", entries); + } + if (obj is Enum && HasEnumMemberAttrValue(obj)) + return GetEnumMemberAttrValue(obj); + + return Convert.ToString(obj, CultureInfo.InvariantCulture); + } + + /// + /// Serializes the given object when not null. Otherwise return null. + /// + /// The object to serialize. + /// Serialized string. + public static string Serialize(object obj) + { + return obj != null ? Newtonsoft.Json.JsonConvert.SerializeObject(obj) : null; + } + + /// + /// Encode string in base64 format. + /// + /// string to be encoded. + /// Encoded string. + public static string Base64Encode(string text) + { + return Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(text)); + } + + /// + /// Convert stream to byte array + /// + /// Input stream to be converted + /// Byte array + public static byte[] ReadAsBytes(Stream inputStream) + { + using (var ms = new MemoryStream()) + { + inputStream.CopyTo(ms); + return ms.ToArray(); + } + } + + /// + /// Select the Content-Type header's value from the given content-type array: + /// if JSON type exists in the given array, use it; + /// otherwise use the first one defined in 'consumes' + /// + /// The Content-Type array to select from. + /// The Content-Type header to use. + public static string SelectHeaderContentType(string[] contentTypes) + { + if (contentTypes.Length == 0) + return null; + + foreach (var contentType in contentTypes) + { + if (IsJsonMime(contentType)) + return contentType; + } + + return contentTypes[0]; // use the first content type specified in 'consumes' + } + + /// + /// Select the Accept header's value from the given accepts array: + /// if JSON exists in the given array, use it; + /// otherwise use all of them (joining into a string) + /// + /// The accepts array to select from. + /// The Accept header to use. + public static string SelectHeaderAccept(string[] accepts) + { + if (accepts.Length == 0) + return null; + + if (accepts.Contains("application/json", StringComparer.OrdinalIgnoreCase)) + return "application/json"; + + return string.Join(",", accepts); + } + + /// + /// Provides a case-insensitive check that a provided content type is a known JSON-like content type. + /// + public static readonly Regex JsonRegex = new Regex("(?i)^(application/json|[^;/ \t]+/[^;/ \t]+[+]json)[ \t]*(;.*)?$"); + + /// + /// Check if the given MIME is a JSON MIME. + /// JSON MIME examples: + /// application/json + /// application/json; charset=UTF8 + /// APPLICATION/JSON + /// application/vnd.company+json + /// + /// MIME + /// Returns True if MIME type is json. + public static bool IsJsonMime(string mime) + { + if (string.IsNullOrWhiteSpace(mime)) return false; + + return JsonRegex.IsMatch(mime) || mime.Equals("application/json-patch+json"); + } + + /// + /// Is the Enum decorated with EnumMember Attribute + /// + /// + /// true if found + private static bool HasEnumMemberAttrValue(object enumVal) + { + if (enumVal == null) + throw new ArgumentNullException(nameof(enumVal)); + var enumType = enumVal.GetType(); + var memInfo = enumType.GetMember(enumVal.ToString() ?? throw new InvalidOperationException()); + var attr = memInfo.FirstOrDefault()?.GetCustomAttributes(false).OfType().FirstOrDefault(); + if (attr != null) return true; + return false; + } + + /// + /// Get the EnumMember value + /// + /// + /// EnumMember value as string otherwise null + private static string GetEnumMemberAttrValue(object enumVal) + { + if (enumVal == null) + throw new ArgumentNullException(nameof(enumVal)); + var enumType = enumVal.GetType(); + var memInfo = enumType.GetMember(enumVal.ToString() ?? throw new InvalidOperationException()); + var attr = memInfo.FirstOrDefault()?.GetCustomAttributes(false).OfType().FirstOrDefault(); + if (attr != null) + { + return attr.Value; + } + return null; + } + } +} diff --git a/Assets/ThirdParty/Org.OpenAPITools/Client/ClientUtils.cs.meta b/Assets/ThirdParty/Org.OpenAPITools/Client/ClientUtils.cs.meta new file mode 100644 index 0000000000..2132771f5e --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Client/ClientUtils.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b27c4007314a2462c91582f15b47c9fc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThirdParty/Org.OpenAPITools/Client/Configuration.cs b/Assets/ThirdParty/Org.OpenAPITools/Client/Configuration.cs new file mode 100644 index 0000000000..fbc0930ec1 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Client/Configuration.cs @@ -0,0 +1,612 @@ +/* + * Icosa API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 0.1.0 + * Generated by: https://github.com/openapitools/openapi-generator.git + */ + + +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net; +using System.Reflection; +using System.Security.Cryptography.X509Certificates; +using System.Text; +using System.Net.Http; +using System.Net.Security; + +namespace Org.OpenAPITools.Client +{ + /// + /// Represents a set of configuration settings + /// + public class Configuration : IReadableConfiguration + { + #region Constants + + /// + /// Version of the package. + /// + /// Version of the package. + public const string Version = "1.0.0"; + + /// + /// Identifier for ISO 8601 DateTime Format + /// + /// See https://msdn.microsoft.com/en-us/library/az4se3k1(v=vs.110).aspx#Anchor_8 for more information. + // ReSharper disable once InconsistentNaming + public const string ISO8601_DATETIME_FORMAT = "o"; + + #endregion Constants + + #region Static Members + + /// + /// Default creation of exceptions for a given method name and response object + /// + public static readonly ExceptionFactory DefaultExceptionFactory = (methodName, response) => + { + var status = (int)response.StatusCode; + if (status >= 400) + { + return new ApiException(status, + string.Format("Error calling {0}: {1}", methodName, response.RawContent), + response.RawContent, response.Headers); + } + if (status == 0) + { + return new ApiException(status, + string.Format("Error calling {0}: {1}", methodName, response.ErrorText), response.ErrorText); + } + return null; + }; + + #endregion Static Members + + #region Private Members + + /// + /// Defines the base path of the target API server. + /// Example: http://localhost:3000/v1/ + /// + private string _basePath; + + private bool _useDefaultCredentials = false; + + /// + /// Gets or sets the API key based on the authentication name. + /// This is the key and value comprising the "secret" for accessing an API. + /// + /// The API key. + private IDictionary _apiKey; + + /// + /// Gets or sets the prefix (e.g. Token) of the API key based on the authentication name. + /// + /// The prefix of the API key. + private IDictionary _apiKeyPrefix; + + private string _dateTimeFormat = ISO8601_DATETIME_FORMAT; + private string _tempFolderPath = Path.GetTempPath(); + + /// + /// Gets or sets the servers defined in the OpenAPI spec. + /// + /// The servers + private IList> _servers; + + /// + /// Gets or sets the operation servers defined in the OpenAPI spec. + /// + /// The operation servers + private IReadOnlyDictionary>> _operationServers; + + #endregion Private Members + + #region Constructors + + /// + /// Initializes a new instance of the class + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("ReSharper", "VirtualMemberCallInConstructor")] + public Configuration() + { + Proxy = null; + UserAgent = WebUtility.UrlEncode("OpenAPI-Generator/1.0.0/csharp"); + BasePath = "http://localhost"; + DefaultHeaders = new ConcurrentDictionary(); + ApiKey = new ConcurrentDictionary(); + ApiKeyPrefix = new ConcurrentDictionary(); + Servers = new List>() + { + { + new Dictionary { + {"url", ""}, + {"description", "No description provided"}, + } + } + }; + OperationServers = new Dictionary>>() + { + }; + + // Setting Timeout has side effects (forces ApiClient creation). + Timeout = 100000; + } + + /// + /// Initializes a new instance of the class + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("ReSharper", "VirtualMemberCallInConstructor")] + public Configuration( + IDictionary defaultHeaders, + IDictionary apiKey, + IDictionary apiKeyPrefix, + string basePath = "http://localhost") : this() + { + if (string.IsNullOrWhiteSpace(basePath)) + throw new ArgumentException("The provided basePath is invalid.", "basePath"); + if (defaultHeaders == null) + throw new ArgumentNullException("defaultHeaders"); + if (apiKey == null) + throw new ArgumentNullException("apiKey"); + if (apiKeyPrefix == null) + throw new ArgumentNullException("apiKeyPrefix"); + + BasePath = basePath; + + foreach (var keyValuePair in defaultHeaders) + { + DefaultHeaders.Add(keyValuePair); + } + + foreach (var keyValuePair in apiKey) + { + ApiKey.Add(keyValuePair); + } + + foreach (var keyValuePair in apiKeyPrefix) + { + ApiKeyPrefix.Add(keyValuePair); + } + } + + #endregion Constructors + + #region Properties + + /// + /// Gets or sets the base path for API access. + /// + public virtual string BasePath + { + get { return _basePath; } + set { _basePath = value; } + } + + /// + /// Determine whether or not the "default credentials" (e.g. the user account under which the current process is running) will be sent along to the server. The default is false. + /// + public virtual bool UseDefaultCredentials + { + get { return _useDefaultCredentials; } + set { _useDefaultCredentials = value; } + } + + /// + /// Gets or sets the default header. + /// + [Obsolete("Use DefaultHeaders instead.")] + public virtual IDictionary DefaultHeader + { + get + { + return DefaultHeaders; + } + set + { + DefaultHeaders = value; + } + } + + /// + /// Gets or sets the default headers. + /// + public virtual IDictionary DefaultHeaders { get; set; } + + /// + /// Gets or sets the HTTP timeout (milliseconds) of ApiClient. Default to 100000 milliseconds. + /// + public virtual int Timeout { get; set; } + + /// + /// Gets or sets the proxy + /// + /// Proxy. + public virtual WebProxy Proxy { get; set; } + + /// + /// Gets or sets the HTTP user agent. + /// + /// Http user agent. + public virtual string UserAgent { get; set; } + + /// + /// Gets or sets the username (HTTP basic authentication). + /// + /// The username. + public virtual string Username { get; set; } + + /// + /// Gets or sets the password (HTTP basic authentication). + /// + /// The password. + public virtual string Password { get; set; } + + /// + /// Gets the API key with prefix. + /// + /// API key identifier (authentication scheme). + /// API key with prefix. + public string GetApiKeyWithPrefix(string apiKeyIdentifier) + { + string apiKeyValue; + ApiKey.TryGetValue(apiKeyIdentifier, out apiKeyValue); + string apiKeyPrefix; + if (ApiKeyPrefix.TryGetValue(apiKeyIdentifier, out apiKeyPrefix)) + { + return apiKeyPrefix + " " + apiKeyValue; + } + + return apiKeyValue; + } + + /// + /// Gets or sets certificate collection to be sent with requests. + /// + /// X509 Certificate collection. + public X509CertificateCollection ClientCertificates { get; set; } + + /// + /// Gets or sets the access token for OAuth2 authentication. + /// + /// This helper property simplifies code generation. + /// + /// The access token. + public virtual string AccessToken { get; set; } + + /// + /// Gets or sets the temporary folder path to store the files downloaded from the server. + /// + /// Folder path. + public virtual string TempFolderPath + { + get { return _tempFolderPath; } + + set + { + if (string.IsNullOrEmpty(value)) + { + _tempFolderPath = Path.GetTempPath(); + return; + } + + // create the directory if it does not exist + if (!Directory.Exists(value)) + { + Directory.CreateDirectory(value); + } + + // check if the path contains directory separator at the end + if (value[value.Length - 1] == Path.DirectorySeparatorChar) + { + _tempFolderPath = value; + } + else + { + _tempFolderPath = value + Path.DirectorySeparatorChar; + } + } + } + + /// + /// Gets or sets the date time format used when serializing in the ApiClient + /// By default, it's set to ISO 8601 - "o", for others see: + /// https://msdn.microsoft.com/en-us/library/az4se3k1(v=vs.110).aspx + /// and https://msdn.microsoft.com/en-us/library/8kb3ddd4(v=vs.110).aspx + /// No validation is done to ensure that the string you're providing is valid + /// + /// The DateTimeFormat string + public virtual string DateTimeFormat + { + get { return _dateTimeFormat; } + set + { + if (string.IsNullOrEmpty(value)) + { + // Never allow a blank or null string, go back to the default + _dateTimeFormat = ISO8601_DATETIME_FORMAT; + return; + } + + // Caution, no validation when you choose date time format other than ISO 8601 + // Take a look at the above links + _dateTimeFormat = value; + } + } + + /// + /// Gets or sets the prefix (e.g. Token) of the API key based on the authentication name. + /// + /// Whatever you set here will be prepended to the value defined in AddApiKey. + /// + /// An example invocation here might be: + /// + /// ApiKeyPrefix["Authorization"] = "Bearer"; + /// + /// … where ApiKey["Authorization"] would then be used to set the value of your bearer token. + /// + /// + /// OAuth2 workflows should set tokens via AccessToken. + /// + /// + /// The prefix of the API key. + public virtual IDictionary ApiKeyPrefix + { + get { return _apiKeyPrefix; } + set + { + if (value == null) + { + throw new InvalidOperationException("ApiKeyPrefix collection may not be null."); + } + _apiKeyPrefix = value; + } + } + + /// + /// Gets or sets the API key based on the authentication name. + /// + /// The API key. + public virtual IDictionary ApiKey + { + get { return _apiKey; } + set + { + if (value == null) + { + throw new InvalidOperationException("ApiKey collection may not be null."); + } + _apiKey = value; + } + } + + /// + /// Gets or sets the servers. + /// + /// The servers. + public virtual IList> Servers + { + get { return _servers; } + set + { + if (value == null) + { + throw new InvalidOperationException("Servers may not be null."); + } + _servers = value; + } + } + + /// + /// Gets or sets the operation servers. + /// + /// The operation servers. + public virtual IReadOnlyDictionary>> OperationServers + { + get { return _operationServers; } + set + { + if (value == null) + { + throw new InvalidOperationException("Operation servers may not be null."); + } + _operationServers = value; + } + } + + /// + /// Returns URL based on server settings without providing values + /// for the variables + /// + /// Array index of the server settings. + /// The server URL. + public string GetServerUrl(int index) + { + return GetServerUrl(Servers, index, null); + } + + /// + /// Returns URL based on server settings. + /// + /// Array index of the server settings. + /// Dictionary of the variables and the corresponding values. + /// The server URL. + public string GetServerUrl(int index, Dictionary inputVariables) + { + return GetServerUrl(Servers, index, inputVariables); + } + + /// + /// Returns URL based on operation server settings. + /// + /// Operation associated with the request path. + /// Array index of the server settings. + /// The operation server URL. + public string GetOperationServerUrl(string operation, int index) + { + return GetOperationServerUrl(operation, index, null); + } + + /// + /// Returns URL based on operation server settings. + /// + /// Operation associated with the request path. + /// Array index of the server settings. + /// Dictionary of the variables and the corresponding values. + /// The operation server URL. + public string GetOperationServerUrl(string operation, int index, Dictionary inputVariables) + { + if (operation != null && OperationServers.TryGetValue(operation, out var operationServer)) + { + return GetServerUrl(operationServer, index, inputVariables); + } + + return null; + } + + /// + /// Returns URL based on server settings. + /// + /// Dictionary of server settings. + /// Array index of the server settings. + /// Dictionary of the variables and the corresponding values. + /// The server URL. + private string GetServerUrl(IList> servers, int index, Dictionary inputVariables) + { + if (index < 0 || index >= servers.Count) + { + throw new InvalidOperationException($"Invalid index {index} when selecting the server. Must be less than {servers.Count}."); + } + + if (inputVariables == null) + { + inputVariables = new Dictionary(); + } + + IReadOnlyDictionary server = servers[index]; + string url = (string)server["url"]; + + if (server.ContainsKey("variables")) + { + // go through each variable and assign a value + foreach (KeyValuePair variable in (IReadOnlyDictionary)server["variables"]) + { + + IReadOnlyDictionary serverVariables = (IReadOnlyDictionary)(variable.Value); + + if (inputVariables.ContainsKey(variable.Key)) + { + if (((List)serverVariables["enum_values"]).Contains(inputVariables[variable.Key])) + { + url = url.Replace("{" + variable.Key + "}", inputVariables[variable.Key]); + } + else + { + throw new InvalidOperationException($"The variable `{variable.Key}` in the server URL has invalid value #{inputVariables[variable.Key]}. Must be {(List)serverVariables["enum_values"]}"); + } + } + else + { + // use default value + url = url.Replace("{" + variable.Key + "}", (string)serverVariables["default_value"]); + } + } + } + + return url; + } + + /// + /// Gets and Sets the RemoteCertificateValidationCallback + /// + public RemoteCertificateValidationCallback RemoteCertificateValidationCallback { get; set; } + + #endregion Properties + + #region Methods + + /// + /// Returns a string with essential information for debugging. + /// + public static string ToDebugReport() + { + string report = "C# SDK (Org.OpenAPITools) Debug Report:\n"; + report += " OS: " + System.Environment.OSVersion + "\n"; + report += " .NET Framework Version: " + System.Environment.Version + "\n"; + report += " Version of the API: 0.1.0\n"; + report += " SDK Package Version: 1.0.0\n"; + + return report; + } + + /// + /// Add Api Key Header. + /// + /// Api Key name. + /// Api Key value. + /// + public void AddApiKey(string key, string value) + { + ApiKey[key] = value; + } + + /// + /// Sets the API key prefix. + /// + /// Api Key name. + /// Api Key value. + public void AddApiKeyPrefix(string key, string value) + { + ApiKeyPrefix[key] = value; + } + + #endregion Methods + + #region Static Members + /// + /// Merge configurations. + /// + /// First configuration. + /// Second configuration. + /// Merged configuration. + public static IReadableConfiguration MergeConfigurations(IReadableConfiguration first, IReadableConfiguration second) + { + if (second == null) return first ?? GlobalConfiguration.Instance; + + Dictionary apiKey = first.ApiKey.ToDictionary(kvp => kvp.Key, kvp => kvp.Value); + Dictionary apiKeyPrefix = first.ApiKeyPrefix.ToDictionary(kvp => kvp.Key, kvp => kvp.Value); + Dictionary defaultHeaders = first.DefaultHeaders.ToDictionary(kvp => kvp.Key, kvp => kvp.Value); + + foreach (var kvp in second.ApiKey) apiKey[kvp.Key] = kvp.Value; + foreach (var kvp in second.ApiKeyPrefix) apiKeyPrefix[kvp.Key] = kvp.Value; + foreach (var kvp in second.DefaultHeaders) defaultHeaders[kvp.Key] = kvp.Value; + + var config = new Configuration + { + ApiKey = apiKey, + ApiKeyPrefix = apiKeyPrefix, + DefaultHeaders = defaultHeaders, + BasePath = second.BasePath ?? first.BasePath, + Timeout = second.Timeout, + Proxy = second.Proxy ?? first.Proxy, + UserAgent = second.UserAgent ?? first.UserAgent, + Username = second.Username ?? first.Username, + Password = second.Password ?? first.Password, + AccessToken = second.AccessToken ?? first.AccessToken, + TempFolderPath = second.TempFolderPath ?? first.TempFolderPath, + DateTimeFormat = second.DateTimeFormat ?? first.DateTimeFormat, + ClientCertificates = second.ClientCertificates ?? first.ClientCertificates, + UseDefaultCredentials = second.UseDefaultCredentials, + RemoteCertificateValidationCallback = second.RemoteCertificateValidationCallback ?? first.RemoteCertificateValidationCallback, + }; + return config; + } + #endregion Static Members + } +} diff --git a/Assets/ThirdParty/Org.OpenAPITools/Client/Configuration.cs.meta b/Assets/ThirdParty/Org.OpenAPITools/Client/Configuration.cs.meta new file mode 100644 index 0000000000..4913850e65 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Client/Configuration.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 343b1b38dff1b45e991f60a1a2ff571b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThirdParty/Org.OpenAPITools/Client/ConnectionException.cs b/Assets/ThirdParty/Org.OpenAPITools/Client/ConnectionException.cs new file mode 100644 index 0000000000..50074d9f9e --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Client/ConnectionException.cs @@ -0,0 +1,29 @@ +/* + * Icosa API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 0.1.0 + * Generated by: https://github.com/openapitools/openapi-generator.git + */ + + +using System; +using UnityEngine.Networking; + +namespace Org.OpenAPITools.Client +{ + public class ConnectionException : Exception + { + public UnityWebRequest.Result Result { get; private set; } + public string Error { get; private set; } + + // NOTE: Cannot keep reference to the request since it will be disposed. + public ConnectionException(UnityWebRequest request) + : base($"result={request.result} error={request.error}") + { + Result = request.result; + Error = request.error ?? ""; + } + } +} diff --git a/Assets/ThirdParty/Org.OpenAPITools/Client/ConnectionException.cs.meta b/Assets/ThirdParty/Org.OpenAPITools/Client/ConnectionException.cs.meta new file mode 100644 index 0000000000..1479548c89 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Client/ConnectionException.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ebebd66bdf14c47b7bd257b33e7e1804 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThirdParty/Org.OpenAPITools/Client/ExceptionFactory.cs b/Assets/ThirdParty/Org.OpenAPITools/Client/ExceptionFactory.cs new file mode 100644 index 0000000000..7b8fba2e12 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Client/ExceptionFactory.cs @@ -0,0 +1,22 @@ +/* + * Icosa API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 0.1.0 + * Generated by: https://github.com/openapitools/openapi-generator.git + */ + + +using System; + +namespace Org.OpenAPITools.Client +{ + /// + /// A delegate to ExceptionFactory method + /// + /// Method name + /// Response + /// Exceptions + public delegate Exception ExceptionFactory(string methodName, IApiResponse response); +} diff --git a/Assets/ThirdParty/Org.OpenAPITools/Client/ExceptionFactory.cs.meta b/Assets/ThirdParty/Org.OpenAPITools/Client/ExceptionFactory.cs.meta new file mode 100644 index 0000000000..7af9e73b58 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Client/ExceptionFactory.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1b3dca7911a294c51b851d2eb4a8ca8d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThirdParty/Org.OpenAPITools/Client/GlobalConfiguration.cs b/Assets/ThirdParty/Org.OpenAPITools/Client/GlobalConfiguration.cs new file mode 100644 index 0000000000..17fb28af08 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Client/GlobalConfiguration.cs @@ -0,0 +1,67 @@ +/* + * Icosa API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 0.1.0 + * Generated by: https://github.com/openapitools/openapi-generator.git + */ + + +using System.Collections.Generic; + +namespace Org.OpenAPITools.Client +{ + /// + /// provides a compile-time extension point for globally configuring + /// API Clients. + /// + /// + /// A customized implementation via partial class may reside in another file and may + /// be excluded from automatic generation via a .openapi-generator-ignore file. + /// + public partial class GlobalConfiguration : Configuration + { + #region Private Members + + private static readonly object GlobalConfigSync = new { }; + private static IReadableConfiguration _globalConfiguration; + + #endregion Private Members + + #region Constructors + + /// + private GlobalConfiguration() + { + } + + /// + public GlobalConfiguration(IDictionary defaultHeader, IDictionary apiKey, IDictionary apiKeyPrefix, string basePath = "http://localhost:3000/api") : base(defaultHeader, apiKey, apiKeyPrefix, basePath) + { + } + + static GlobalConfiguration() + { + Instance = new GlobalConfiguration(); + } + + #endregion Constructors + + /// + /// Gets or sets the default Configuration. + /// + /// Configuration. + public static IReadableConfiguration Instance + { + get { return _globalConfiguration; } + set + { + lock (GlobalConfigSync) + { + _globalConfiguration = value; + } + } + } + } +} diff --git a/Assets/ThirdParty/Org.OpenAPITools/Client/GlobalConfiguration.cs.meta b/Assets/ThirdParty/Org.OpenAPITools/Client/GlobalConfiguration.cs.meta new file mode 100644 index 0000000000..36f801f265 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Client/GlobalConfiguration.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7a214e7285ed44527938b547788aa53e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThirdParty/Org.OpenAPITools/Client/IApiAccessor.cs b/Assets/ThirdParty/Org.OpenAPITools/Client/IApiAccessor.cs new file mode 100644 index 0000000000..a8e6bb4342 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Client/IApiAccessor.cs @@ -0,0 +1,37 @@ +/* + * Icosa API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 0.1.0 + * Generated by: https://github.com/openapitools/openapi-generator.git + */ + + +using System; + +namespace Org.OpenAPITools.Client +{ + /// + /// Represents configuration aspects required to interact with the API endpoints. + /// + public interface IApiAccessor + { + /// + /// Gets or sets the configuration object + /// + /// An instance of the Configuration + IReadableConfiguration Configuration { get; set; } + + /// + /// Gets the base path of the API client. + /// + /// The base path + string GetBasePath(); + + /// + /// Provides a factory method hook for the creation of exceptions. + /// + ExceptionFactory ExceptionFactory { get; set; } + } +} diff --git a/Assets/ThirdParty/Org.OpenAPITools/Client/IApiAccessor.cs.meta b/Assets/ThirdParty/Org.OpenAPITools/Client/IApiAccessor.cs.meta new file mode 100644 index 0000000000..4e83e55a28 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Client/IApiAccessor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 56284ecd7a31c4f20ae39175e72233e4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThirdParty/Org.OpenAPITools/Client/IAsynchronousClient.cs b/Assets/ThirdParty/Org.OpenAPITools/Client/IAsynchronousClient.cs new file mode 100644 index 0000000000..a41541642e --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Client/IAsynchronousClient.cs @@ -0,0 +1,100 @@ +/* + * Icosa API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 0.1.0 + * Generated by: https://github.com/openapitools/openapi-generator.git + */ + + +using System; +using System.Threading.Tasks; + +namespace Org.OpenAPITools.Client +{ + /// + /// Contract for Asynchronous RESTful API interactions. + /// + /// This interface allows consumers to provide a custom API accessor client. + /// + public interface IAsynchronousClient + { + /// + /// Executes a non-blocking call to some using the GET http verb. + /// + /// The relative path to invoke. + /// The request parameters to pass along to the client. + /// Per-request configurable settings. + /// Cancellation Token to cancel the request. + /// The return type. + /// A task eventually representing the response data, decorated with + Task> GetAsync(string path, RequestOptions options, IReadableConfiguration configuration = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + + /// + /// Executes a non-blocking call to some using the POST http verb. + /// + /// The relative path to invoke. + /// The request parameters to pass along to the client. + /// Per-request configurable settings. + /// Cancellation Token to cancel the request. + /// The return type. + /// A task eventually representing the response data, decorated with + Task> PostAsync(string path, RequestOptions options, IReadableConfiguration configuration = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + + /// + /// Executes a non-blocking call to some using the PUT http verb. + /// + /// The relative path to invoke. + /// The request parameters to pass along to the client. + /// Per-request configurable settings. + /// Cancellation Token to cancel the request. + /// The return type. + /// A task eventually representing the response data, decorated with + Task> PutAsync(string path, RequestOptions options, IReadableConfiguration configuration = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + + /// + /// Executes a non-blocking call to some using the DELETE http verb. + /// + /// The relative path to invoke. + /// The request parameters to pass along to the client. + /// Per-request configurable settings. + /// Cancellation Token to cancel the request. + /// The return type. + /// A task eventually representing the response data, decorated with + Task> DeleteAsync(string path, RequestOptions options, IReadableConfiguration configuration = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + + /// + /// Executes a non-blocking call to some using the HEAD http verb. + /// + /// The relative path to invoke. + /// The request parameters to pass along to the client. + /// Per-request configurable settings. + /// Cancellation Token to cancel the request. + /// The return type. + /// A task eventually representing the response data, decorated with + Task> HeadAsync(string path, RequestOptions options, IReadableConfiguration configuration = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + + /// + /// Executes a non-blocking call to some using the OPTIONS http verb. + /// + /// The relative path to invoke. + /// The request parameters to pass along to the client. + /// Per-request configurable settings. + /// Cancellation Token to cancel the request. + /// The return type. + /// A task eventually representing the response data, decorated with + Task> OptionsAsync(string path, RequestOptions options, IReadableConfiguration configuration = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + + /// + /// Executes a non-blocking call to some using the PATCH http verb. + /// + /// The relative path to invoke. + /// The request parameters to pass along to the client. + /// Per-request configurable settings. + /// Cancellation Token to cancel the request. + /// The return type. + /// A task eventually representing the response data, decorated with + Task> PatchAsync(string path, RequestOptions options, IReadableConfiguration configuration = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + } +} diff --git a/Assets/ThirdParty/Org.OpenAPITools/Client/IAsynchronousClient.cs.meta b/Assets/ThirdParty/Org.OpenAPITools/Client/IAsynchronousClient.cs.meta new file mode 100644 index 0000000000..d7b1ee80ec --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Client/IAsynchronousClient.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7eb059d43bef1497dbefe1e32059de32 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThirdParty/Org.OpenAPITools/Client/IReadableConfiguration.cs b/Assets/ThirdParty/Org.OpenAPITools/Client/IReadableConfiguration.cs new file mode 100644 index 0000000000..c326b57a08 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Client/IReadableConfiguration.cs @@ -0,0 +1,141 @@ +/* + * Icosa API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 0.1.0 + * Generated by: https://github.com/openapitools/openapi-generator.git + */ + + +using System; +using System.Collections.Generic; +using System.Net; +using System.Net.Security; +using System.Security.Cryptography.X509Certificates; + +namespace Org.OpenAPITools.Client +{ + /// + /// Represents a readable-only configuration contract. + /// + public interface IReadableConfiguration + { + /// + /// Gets the access token. + /// + /// Access token. + string AccessToken { get; } + + /// + /// Gets the API key. + /// + /// API key. + IDictionary ApiKey { get; } + + /// + /// Gets the API key prefix. + /// + /// API key prefix. + IDictionary ApiKeyPrefix { get; } + + /// + /// Gets the base path. + /// + /// Base path. + string BasePath { get; } + + /// + /// Gets the date time format. + /// + /// Date time format. + string DateTimeFormat { get; } + + /// + /// Gets the default header. + /// + /// Default header. + [Obsolete("Use DefaultHeaders instead.")] + IDictionary DefaultHeader { get; } + + /// + /// Gets the default headers. + /// + /// Default headers. + IDictionary DefaultHeaders { get; } + + /// + /// Gets the temp folder path. + /// + /// Temp folder path. + string TempFolderPath { get; } + + /// + /// Gets the HTTP connection timeout (in milliseconds) + /// + /// HTTP connection timeout. + int Timeout { get; } + + /// + /// Gets the proxy. + /// + /// Proxy. + WebProxy Proxy { get; } + + /// + /// Gets the user agent. + /// + /// User agent. + string UserAgent { get; } + + /// + /// Gets the username. + /// + /// Username. + string Username { get; } + + /// + /// Gets the password. + /// + /// Password. + string Password { get; } + + /// + /// Determine whether or not the "default credentials" (e.g. the user account under which the current process is running) will be sent along to the server. The default is false. + /// + bool UseDefaultCredentials { get; } + + /// + /// Get the servers associated with the operation. + /// + /// Operation servers. + IReadOnlyDictionary>> OperationServers { get; } + + /// + /// Gets the API key with prefix. + /// + /// API key identifier (authentication scheme). + /// API key with prefix. + string GetApiKeyWithPrefix(string apiKeyIdentifier); + + /// + /// Gets the Operation server url at the provided index. + /// + /// Operation server name. + /// Index of the operation server settings. + /// + string GetOperationServerUrl(string operation, int index); + + /// + /// Gets certificate collection to be sent with requests. + /// + /// X509 Certificate collection. + X509CertificateCollection ClientCertificates { get; } + + /// + /// Callback function for handling the validation of remote certificates. Useful for certificate pinning and + /// overriding certificate errors in the scope of a request. + /// + RemoteCertificateValidationCallback RemoteCertificateValidationCallback { get; } + } +} diff --git a/Assets/ThirdParty/Org.OpenAPITools/Client/IReadableConfiguration.cs.meta b/Assets/ThirdParty/Org.OpenAPITools/Client/IReadableConfiguration.cs.meta new file mode 100644 index 0000000000..eb52e0a603 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Client/IReadableConfiguration.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c00c05b0a57104c01887d215eb67871c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThirdParty/Org.OpenAPITools/Client/ISynchronousClient.cs b/Assets/ThirdParty/Org.OpenAPITools/Client/ISynchronousClient.cs new file mode 100644 index 0000000000..17551a97d9 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Client/ISynchronousClient.cs @@ -0,0 +1,93 @@ +/* + * Icosa API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 0.1.0 + * Generated by: https://github.com/openapitools/openapi-generator.git + */ + + +using System; +using System.IO; + +namespace Org.OpenAPITools.Client +{ + /// + /// Contract for Synchronous RESTful API interactions. + /// + /// This interface allows consumers to provide a custom API accessor client. + /// + public interface ISynchronousClient + { + /// + /// Executes a blocking call to some using the GET http verb. + /// + /// The relative path to invoke. + /// The request parameters to pass along to the client. + /// Per-request configurable settings. + /// The return type. + /// The response data, decorated with + ApiResponse Get(string path, RequestOptions options, IReadableConfiguration configuration = null); + + /// + /// Executes a blocking call to some using the POST http verb. + /// + /// The relative path to invoke. + /// The request parameters to pass along to the client. + /// Per-request configurable settings. + /// The return type. + /// The response data, decorated with + ApiResponse Post(string path, RequestOptions options, IReadableConfiguration configuration = null); + + /// + /// Executes a blocking call to some using the PUT http verb. + /// + /// The relative path to invoke. + /// The request parameters to pass along to the client. + /// Per-request configurable settings. + /// The return type. + /// The response data, decorated with + ApiResponse Put(string path, RequestOptions options, IReadableConfiguration configuration = null); + + /// + /// Executes a blocking call to some using the DELETE http verb. + /// + /// The relative path to invoke. + /// The request parameters to pass along to the client. + /// Per-request configurable settings. + /// The return type. + /// The response data, decorated with + ApiResponse Delete(string path, RequestOptions options, IReadableConfiguration configuration = null); + + /// + /// Executes a blocking call to some using the HEAD http verb. + /// + /// The relative path to invoke. + /// The request parameters to pass along to the client. + /// Per-request configurable settings. + /// The return type. + /// The response data, decorated with + ApiResponse Head(string path, RequestOptions options, IReadableConfiguration configuration = null); + + /// + /// Executes a blocking call to some using the OPTIONS http verb. + /// + /// The relative path to invoke. + /// The request parameters to pass along to the client. + /// Per-request configurable settings. + /// The return type. + /// The response data, decorated with + ApiResponse Options(string path, RequestOptions options, IReadableConfiguration configuration = null); + + /// + /// Executes a blocking call to some using the PATCH http verb. + /// + /// The relative path to invoke. + /// The request parameters to pass along to the client. + /// Per-request configurable settings. + /// The return type. + /// The response data, decorated with + ApiResponse Patch(string path, RequestOptions options, IReadableConfiguration configuration = null); + } +} diff --git a/Assets/ThirdParty/Org.OpenAPITools/Client/ISynchronousClient.cs.meta b/Assets/ThirdParty/Org.OpenAPITools/Client/ISynchronousClient.cs.meta new file mode 100644 index 0000000000..0653acf151 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Client/ISynchronousClient.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f07939cfa05c148409eaf097a177fd12 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThirdParty/Org.OpenAPITools/Client/Multimap.cs b/Assets/ThirdParty/Org.OpenAPITools/Client/Multimap.cs new file mode 100644 index 0000000000..3673b10fe2 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Client/Multimap.cs @@ -0,0 +1,295 @@ +/* + * Icosa API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 0.1.0 + * Generated by: https://github.com/openapitools/openapi-generator.git + */ + + +using System; +using System.Collections; +using System.Collections.Generic; + +namespace Org.OpenAPITools.Client +{ + /// + /// A dictionary in which one key has many associated values. + /// + /// The type of the key + /// The type of the value associated with the key. + public class Multimap : IDictionary> + { + #region Private Fields + + private readonly Dictionary> _dictionary; + + #endregion Private Fields + + #region Constructors + + /// + /// Empty Constructor. + /// + public Multimap() + { + _dictionary = new Dictionary>(); + } + + /// + /// Constructor with comparer. + /// + /// + public Multimap(IEqualityComparer comparer) + { + _dictionary = new Dictionary>(comparer); + } + + #endregion Constructors + + #region Enumerators + + /// + /// To get the enumerator. + /// + /// Enumerator + public IEnumerator>> GetEnumerator() + { + return _dictionary.GetEnumerator(); + } + + /// + /// To get the enumerator. + /// + /// Enumerator + IEnumerator IEnumerable.GetEnumerator() + { + return _dictionary.GetEnumerator(); + } + + #endregion Enumerators + + #region Public Members + /// + /// Add values to Multimap + /// + /// Key value pair + public void Add(KeyValuePair> item) + { + if (!TryAdd(item.Key, item.Value)) + throw new InvalidOperationException("Could not add values to Multimap."); + } + + /// + /// Add Multimap to Multimap + /// + /// Multimap + public void Add(Multimap multimap) + { + foreach (var item in multimap) + { + if (!TryAdd(item.Key, item.Value)) + throw new InvalidOperationException("Could not add values to Multimap."); + } + } + + /// + /// Clear Multimap + /// + public void Clear() + { + _dictionary.Clear(); + } + + /// + /// Determines whether Multimap contains the specified item. + /// + /// Key value pair + /// Method needs to be implemented + /// true if the Multimap contains the item; otherwise, false. + public bool Contains(KeyValuePair> item) + { + throw new NotImplementedException(); + } + + /// + /// Copy items of the Multimap to an array, + /// starting at a particular array index. + /// + /// The array that is the destination of the items copied + /// from Multimap. The array must have zero-based indexing. + /// The zero-based index in array at which copying begins. + /// Method needs to be implemented + public void CopyTo(KeyValuePair>[] array, int arrayIndex) + { + throw new NotImplementedException(); + } + + /// + /// Removes the specified item from the Multimap. + /// + /// Key value pair + /// true if the item is successfully removed; otherwise, false. + /// Method needs to be implemented + public bool Remove(KeyValuePair> item) + { + throw new NotImplementedException(); + } + + /// + /// Gets the number of items contained in the Multimap. + /// + public int Count => _dictionary.Count; + + /// + /// Gets a value indicating whether the Multimap is read-only. + /// + public bool IsReadOnly => false; + + /// + /// Adds an item with the provided key and value to the Multimap. + /// + /// The object to use as the key of the item to add. + /// The object to use as the value of the item to add. + /// Thrown when couldn't add the value to Multimap. + public void Add(TKey key, IList value) + { + if (value != null && value.Count > 0) + { + if (_dictionary.TryGetValue(key, out var list)) + { + foreach (var k in value) list.Add(k); + } + else + { + list = new List(value); + if (!TryAdd(key, list)) + throw new InvalidOperationException("Could not add values to Multimap."); + } + } + } + + /// + /// Determines whether the Multimap contains an item with the specified key. + /// + /// The key to locate in the Multimap. + /// true if the Multimap contains an item with + /// the key; otherwise, false. + public bool ContainsKey(TKey key) + { + return _dictionary.ContainsKey(key); + } + + /// + /// Removes item with the specified key from the Multimap. + /// + /// The key to locate in the Multimap. + /// true if the item is successfully removed; otherwise, false. + public bool Remove(TKey key) + { + return TryRemove(key, out var _); + } + + /// + /// Gets the value associated with the specified key. + /// + /// The key whose value to get. + /// When this method returns, the value associated with the specified key, if the + /// key is found; otherwise, the default value for the type of the value parameter. + /// This parameter is passed uninitialized. + /// true if the object that implements Multimap contains + /// an item with the specified key; otherwise, false. + public bool TryGetValue(TKey key, out IList value) + { + return _dictionary.TryGetValue(key, out value); + } + + /// + /// Gets or sets the item with the specified key. + /// + /// The key of the item to get or set. + /// The value of the specified key. + public IList this[TKey key] + { + get => _dictionary[key]; + set => _dictionary[key] = value; + } + + /// + /// Gets a System.Collections.Generic.ICollection containing the keys of the Multimap. + /// + public ICollection Keys => _dictionary.Keys; + + /// + /// Gets a System.Collections.Generic.ICollection containing the values of the Multimap. + /// + public ICollection> Values => _dictionary.Values; + + /// + /// Copy the items of the Multimap to an System.Array, + /// starting at a particular System.Array index. + /// + /// The one-dimensional System.Array that is the destination of the items copied + /// from Multimap. The System.Array must have zero-based indexing. + /// The zero-based index in array at which copying begins. + public void CopyTo(Array array, int index) + { + ((ICollection)_dictionary).CopyTo(array, index); + } + + /// + /// Adds an item with the provided key and value to the Multimap. + /// + /// The object to use as the key of the item to add. + /// The object to use as the value of the item to add. + /// Thrown when couldn't add value to Multimap. + public void Add(TKey key, TValue value) + { + if (value != null) + { + if (_dictionary.TryGetValue(key, out var list)) + { + list.Add(value); + } + else + { + list = new List { value }; + if (!TryAdd(key, list)) + throw new InvalidOperationException("Could not add value to Multimap."); + } + } + } + + #endregion Public Members + + #region Private Members + + /** + * Helper method to encapsulate generator differences between dictionary types. + */ + private bool TryRemove(TKey key, out IList value) + { + _dictionary.TryGetValue(key, out value); + return _dictionary.Remove(key); + } + + /** + * Helper method to encapsulate generator differences between dictionary types. + */ + private bool TryAdd(TKey key, IList value) + { + try + { + _dictionary.Add(key, value); + } + catch (ArgumentException) + { + return false; + } + + return true; + } + #endregion Private Members + } +} diff --git a/Assets/ThirdParty/Org.OpenAPITools/Client/Multimap.cs.meta b/Assets/ThirdParty/Org.OpenAPITools/Client/Multimap.cs.meta new file mode 100644 index 0000000000..3d1c999995 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Client/Multimap.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 85d9a5b5e437e44879e1301cb19aa4f2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThirdParty/Org.OpenAPITools/Client/OpenAPIDateConverter.cs b/Assets/ThirdParty/Org.OpenAPITools/Client/OpenAPIDateConverter.cs new file mode 100644 index 0000000000..4dd770eca9 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Client/OpenAPIDateConverter.cs @@ -0,0 +1,29 @@ +/* + * Icosa API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 0.1.0 + * Generated by: https://github.com/openapitools/openapi-generator.git + */ + +using Newtonsoft.Json.Converters; + +namespace Org.OpenAPITools.Client +{ + /// + /// Formatter for 'date' openapi formats ss defined by full-date - RFC3339 + /// see https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#data-types + /// + public class OpenAPIDateConverter : IsoDateTimeConverter + { + /// + /// Initializes a new instance of the class. + /// + public OpenAPIDateConverter() + { + // full-date = date-fullyear "-" date-month "-" date-mday + DateTimeFormat = "yyyy-MM-dd"; + } + } +} diff --git a/Assets/ThirdParty/Org.OpenAPITools/Client/OpenAPIDateConverter.cs.meta b/Assets/ThirdParty/Org.OpenAPITools/Client/OpenAPIDateConverter.cs.meta new file mode 100644 index 0000000000..250cca9041 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Client/OpenAPIDateConverter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e052385fe3f8d41ca8607fb55af93963 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThirdParty/Org.OpenAPITools/Client/RequestOptions.cs b/Assets/ThirdParty/Org.OpenAPITools/Client/RequestOptions.cs new file mode 100644 index 0000000000..4c9efae525 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Client/RequestOptions.cs @@ -0,0 +1,68 @@ +/* + * Icosa API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 0.1.0 + * Generated by: https://github.com/openapitools/openapi-generator.git + */ + + +using System; +using System.Collections.Generic; +using System.IO; +using System.Net; + +namespace Org.OpenAPITools.Client +{ + /// + /// A container for generalized request inputs. This type allows consumers to extend the request functionality + /// by abstracting away from the default (built-in) request framework (e.g. RestSharp). + /// + public class RequestOptions + { + /// + /// Parameters to be bound to path parts of the Request's URL + /// + public Dictionary PathParameters { get; set; } + + /// + /// Query parameters to be applied to the request. + /// Keys may have 1 or more values associated. + /// + public Multimap QueryParameters { get; set; } + + /// + /// Header parameters to be applied to to the request. + /// Keys may have 1 or more values associated. + /// + public Multimap HeaderParameters { get; set; } + + /// + /// Form parameters to be sent along with the request. + /// + public Dictionary FormParameters { get; set; } + + /// + /// Cookies to be sent along with the request. + /// + public List Cookies { get; set; } + + /// + /// Any data associated with a request body. + /// + public Object Data { get; set; } + + /// + /// Constructs a new instance of + /// + public RequestOptions() + { + PathParameters = new Dictionary(); + QueryParameters = new Multimap(); + HeaderParameters = new Multimap(); + FormParameters = new Dictionary(); + Cookies = new List(); + } + } +} diff --git a/Assets/ThirdParty/Org.OpenAPITools/Client/RequestOptions.cs.meta b/Assets/ThirdParty/Org.OpenAPITools/Client/RequestOptions.cs.meta new file mode 100644 index 0000000000..1abe89a112 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Client/RequestOptions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2b386f103d2e34b39b021c9d06864afa +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThirdParty/Org.OpenAPITools/Client/UnexpectedResponseException.cs b/Assets/ThirdParty/Org.OpenAPITools/Client/UnexpectedResponseException.cs new file mode 100644 index 0000000000..4d0ed3e922 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Client/UnexpectedResponseException.cs @@ -0,0 +1,34 @@ +/* + * Icosa API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 0.1.0 + * Generated by: https://github.com/openapitools/openapi-generator.git + */ + + +using System; +using UnityEngine.Networking; + +namespace Org.OpenAPITools.Client +{ + // Thrown when a backend doesn't return an expected response based on the expected type + // of the response data. + public class UnexpectedResponseException : Exception + { + public int ErrorCode { get; private set; } + + // NOTE: Cannot keep reference to the request since it will be disposed. + public UnexpectedResponseException(UnityWebRequest request, System.Type type, string extra = "") + : base(CreateMessage(request, type, extra)) + { + ErrorCode = (int)request.responseCode; + } + + private static string CreateMessage(UnityWebRequest request, System.Type type, string extra) + { + return $"httpcode={request.responseCode}, expected {type.Name} but got data: {extra}"; + } + } +} diff --git a/Assets/ThirdParty/Org.OpenAPITools/Client/UnexpectedResponseException.cs.meta b/Assets/ThirdParty/Org.OpenAPITools/Client/UnexpectedResponseException.cs.meta new file mode 100644 index 0000000000..6c8a537af1 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Client/UnexpectedResponseException.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 90a213292d9b341d08513f39e9877e18 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThirdParty/Org.OpenAPITools/Client/WebRequestPathBuilder.cs b/Assets/ThirdParty/Org.OpenAPITools/Client/WebRequestPathBuilder.cs new file mode 100644 index 0000000000..d8958eb5bd --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Client/WebRequestPathBuilder.cs @@ -0,0 +1,53 @@ +/* + * Icosa API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 0.1.0 + * Generated by: https://github.com/openapitools/openapi-generator.git + */ + +using System; +using System.Collections.Generic; + +namespace Org.OpenAPITools.Client +{ + /// + /// A URI builder + /// + class WebRequestPathBuilder + { + private string _baseUrl; + private string _path; + private string _query = "?"; + public WebRequestPathBuilder(string baseUrl, string path) + { + _baseUrl = baseUrl; + _path = path; + } + + public void AddPathParameters(Dictionary parameters) + { + foreach (var parameter in parameters) + { + _path = _path.Replace("{" + parameter.Key + "}", Uri.EscapeDataString(parameter.Value)); + } + } + + public void AddQueryParameters(Multimap parameters) + { + foreach (var parameter in parameters) + { + foreach (var value in parameter.Value) + { + _query = _query + parameter.Key + "=" + Uri.EscapeDataString(value) + "&"; + } + } + } + + public string GetFullUri() + { + return _baseUrl + _path + _query.Substring(0, _query.Length - 1); + } + } +} diff --git a/Assets/ThirdParty/Org.OpenAPITools/Client/WebRequestPathBuilder.cs.meta b/Assets/ThirdParty/Org.OpenAPITools/Client/WebRequestPathBuilder.cs.meta new file mode 100644 index 0000000000..af41377b84 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Client/WebRequestPathBuilder.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2d783b44327494ed3b72ee0b248206ad +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThirdParty/Org.OpenAPITools/Model.meta b/Assets/ThirdParty/Org.OpenAPITools/Model.meta new file mode 100644 index 0000000000..5c25fe715d --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Model.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 882e36e1001f443fb894152eb6d56694 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThirdParty/Org.OpenAPITools/Model/AbstractOpenAPISchema.cs b/Assets/ThirdParty/Org.OpenAPITools/Model/AbstractOpenAPISchema.cs new file mode 100644 index 0000000000..299c408b39 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Model/AbstractOpenAPISchema.cs @@ -0,0 +1,76 @@ +/* + * Icosa API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 0.1.0 + * Generated by: https://github.com/openapitools/openapi-generator.git + */ + + +using System; +using Newtonsoft.Json; +using Newtonsoft.Json.Serialization; + +namespace Org.OpenAPITools.Model +{ + /// + /// Abstract base class for oneOf, anyOf schemas in the OpenAPI specification + /// + public abstract partial class AbstractOpenAPISchema + { + /// + /// Custom JSON serializer + /// + static public readonly JsonSerializerSettings SerializerSettings = new JsonSerializerSettings + { + // OpenAPI generated types generally hide default constructors. + ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor, + MissingMemberHandling = MissingMemberHandling.Error, + ContractResolver = new DefaultContractResolver + { + NamingStrategy = new CamelCaseNamingStrategy + { + OverrideSpecifiedNames = false + } + } + }; + + /// + /// Custom JSON serializer for objects with additional properties + /// + static public readonly JsonSerializerSettings AdditionalPropertiesSerializerSettings = new JsonSerializerSettings + { + // OpenAPI generated types generally hide default constructors. + ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor, + MissingMemberHandling = MissingMemberHandling.Ignore, + ContractResolver = new DefaultContractResolver + { + NamingStrategy = new CamelCaseNamingStrategy + { + OverrideSpecifiedNames = false + } + } + }; + + /// + /// Gets or Sets the actual instance + /// + public abstract Object ActualInstance { get; set; } + + /// + /// Gets or Sets IsNullable to indicate whether the instance is nullable + /// + public bool IsNullable { get; protected set; } + + /// + /// Gets or Sets the schema type, which can be either `oneOf` or `anyOf` + /// + public string SchemaType { get; protected set; } + + /// + /// Converts the instance into JSON string. + /// + public abstract string ToJson(); + } +} diff --git a/Assets/ThirdParty/Org.OpenAPITools/Model/AbstractOpenAPISchema.cs.meta b/Assets/ThirdParty/Org.OpenAPITools/Model/AbstractOpenAPISchema.cs.meta new file mode 100644 index 0000000000..28f5ebde3e --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Model/AbstractOpenAPISchema.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bffa34a5f84c748b1bb4bff1df3a370d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThirdParty/Org.OpenAPITools/Model/Asset.cs b/Assets/ThirdParty/Org.OpenAPITools/Model/Asset.cs new file mode 100644 index 0000000000..3b21ac9fc0 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Model/Asset.cs @@ -0,0 +1,371 @@ +/* + * Icosa API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 0.1.0 + * Generated by: https://github.com/openapitools/openapi-generator.git + */ + + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.IO; +using System.Runtime.Serialization; +using System.Text; +using System.Text.RegularExpressions; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using Newtonsoft.Json.Linq; +using OpenAPIDateConverter = Org.OpenAPITools.Client.OpenAPIDateConverter; + +namespace Org.OpenAPITools.Model +{ + /// + /// Asset + /// + [DataContract(Name = "Asset")] + public partial class Asset : IEquatable + { + /// + /// Initializes a new instance of the class. + /// + [JsonConstructorAttribute] + protected Asset() { } + /// + /// Initializes a new instance of the class. + /// + /// id (required). + /// url. + /// formats (required). + /// name (required). + /// description. + /// owner (required). + /// visibility (required). + /// curated. + /// polyid. + /// polydata. + /// thumbnail. + /// ownername (required). + /// ownerurl (required). + public Asset(string id = default(string), string url = default(string), List formats = default(List), string name = default(string), string description = default(string), string owner = default(string), string visibility = default(string), bool curated = default(bool), string polyid = default(string), PolyAsset polydata = default(PolyAsset), string thumbnail = default(string), string ownername = default(string), string ownerurl = default(string)) + { + // to ensure "id" is required (not null) + if (id == null) + { + throw new ArgumentNullException("id is a required property for Asset and cannot be null"); + } + this.Id = id; + // to ensure "formats" is required (not null) + if (formats == null) + { + throw new ArgumentNullException("formats is a required property for Asset and cannot be null"); + } + this.Formats = formats; + // to ensure "name" is required (not null) + if (name == null) + { + throw new ArgumentNullException("name is a required property for Asset and cannot be null"); + } + this.Name = name; + // to ensure "owner" is required (not null) + if (owner == null) + { + throw new ArgumentNullException("owner is a required property for Asset and cannot be null"); + } + this.Owner = owner; + // to ensure "visibility" is required (not null) + if (visibility == null) + { + throw new ArgumentNullException("visibility is a required property for Asset and cannot be null"); + } + this.Visibility = visibility; + // to ensure "ownername" is required (not null) + if (ownername == null) + { + throw new ArgumentNullException("ownername is a required property for Asset and cannot be null"); + } + this.Ownername = ownername; + // to ensure "ownerurl" is required (not null) + if (ownerurl == null) + { + throw new ArgumentNullException("ownerurl is a required property for Asset and cannot be null"); + } + this.Ownerurl = ownerurl; + this.Url = url; + this.Description = description; + this.Curated = curated; + this.Polyid = polyid; + this.Polydata = polydata; + this.Thumbnail = thumbnail; + } + + /// + /// Gets or Sets Id + /// + [DataMember(Name = "id", IsRequired = true, EmitDefaultValue = true)] + public string Id { get; set; } + + /// + /// Gets or Sets Url + /// + [DataMember(Name = "url", EmitDefaultValue = false)] + public string Url { get; set; } + + /// + /// Gets or Sets Formats + /// + [DataMember(Name = "formats", IsRequired = true, EmitDefaultValue = true)] + public List Formats { get; set; } + + /// + /// Gets or Sets Name + /// + [DataMember(Name = "name", IsRequired = true, EmitDefaultValue = true)] + public string Name { get; set; } + + /// + /// Gets or Sets Description + /// + [DataMember(Name = "description", EmitDefaultValue = false)] + public string Description { get; set; } + + /// + /// Gets or Sets Owner + /// + [DataMember(Name = "owner", IsRequired = true, EmitDefaultValue = true)] + public string Owner { get; set; } + + /// + /// Gets or Sets Visibility + /// + [DataMember(Name = "visibility", IsRequired = true, EmitDefaultValue = true)] + public string Visibility { get; set; } + + /// + /// Gets or Sets Curated + /// + [DataMember(Name = "curated", EmitDefaultValue = true)] + public bool Curated { get; set; } + + /// + /// Gets or Sets Polyid + /// + [DataMember(Name = "polyid", EmitDefaultValue = false)] + public string Polyid { get; set; } + + /// + /// Gets or Sets Polydata + /// + [DataMember(Name = "polydata", EmitDefaultValue = false)] + public PolyAsset Polydata { get; set; } + + /// + /// Gets or Sets Thumbnail + /// + [DataMember(Name = "thumbnail", EmitDefaultValue = false)] + public string Thumbnail { get; set; } + + /// + /// Gets or Sets Ownername + /// + [DataMember(Name = "ownername", IsRequired = true, EmitDefaultValue = true)] + public string Ownername { get; set; } + + /// + /// Gets or Sets Ownerurl + /// + [DataMember(Name = "ownerurl", IsRequired = true, EmitDefaultValue = true)] + public string Ownerurl { get; set; } + + /// + /// Returns the string presentation of the object + /// + /// String presentation of the object + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + sb.Append("class Asset {\n"); + sb.Append(" Id: ").Append(Id).Append("\n"); + sb.Append(" Url: ").Append(Url).Append("\n"); + sb.Append(" Formats: ").Append(Formats).Append("\n"); + sb.Append(" Name: ").Append(Name).Append("\n"); + sb.Append(" Description: ").Append(Description).Append("\n"); + sb.Append(" Owner: ").Append(Owner).Append("\n"); + sb.Append(" Visibility: ").Append(Visibility).Append("\n"); + sb.Append(" Curated: ").Append(Curated).Append("\n"); + sb.Append(" Polyid: ").Append(Polyid).Append("\n"); + sb.Append(" Polydata: ").Append(Polydata).Append("\n"); + sb.Append(" Thumbnail: ").Append(Thumbnail).Append("\n"); + sb.Append(" Ownername: ").Append(Ownername).Append("\n"); + sb.Append(" Ownerurl: ").Append(Ownerurl).Append("\n"); + sb.Append("}\n"); + return sb.ToString(); + } + + /// + /// Returns the JSON string presentation of the object + /// + /// JSON string presentation of the object + public virtual string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented); + } + + /// + /// Returns true if objects are equal + /// + /// Object to be compared + /// Boolean + public override bool Equals(object input) + { + return this.Equals(input as Asset); + } + + /// + /// Returns true if Asset instances are equal + /// + /// Instance of Asset to be compared + /// Boolean + public bool Equals(Asset input) + { + if (input == null) + { + return false; + } + return + ( + this.Id == input.Id || + (this.Id != null && + this.Id.Equals(input.Id)) + ) && + ( + this.Url == input.Url || + (this.Url != null && + this.Url.Equals(input.Url)) + ) && + ( + this.Formats == input.Formats || + this.Formats != null && + input.Formats != null && + this.Formats.SequenceEqual(input.Formats) + ) && + ( + this.Name == input.Name || + (this.Name != null && + this.Name.Equals(input.Name)) + ) && + ( + this.Description == input.Description || + (this.Description != null && + this.Description.Equals(input.Description)) + ) && + ( + this.Owner == input.Owner || + (this.Owner != null && + this.Owner.Equals(input.Owner)) + ) && + ( + this.Visibility == input.Visibility || + (this.Visibility != null && + this.Visibility.Equals(input.Visibility)) + ) && + ( + this.Curated == input.Curated || + this.Curated.Equals(input.Curated) + ) && + ( + this.Polyid == input.Polyid || + (this.Polyid != null && + this.Polyid.Equals(input.Polyid)) + ) && + ( + this.Polydata == input.Polydata || + (this.Polydata != null && + this.Polydata.Equals(input.Polydata)) + ) && + ( + this.Thumbnail == input.Thumbnail || + (this.Thumbnail != null && + this.Thumbnail.Equals(input.Thumbnail)) + ) && + ( + this.Ownername == input.Ownername || + (this.Ownername != null && + this.Ownername.Equals(input.Ownername)) + ) && + ( + this.Ownerurl == input.Ownerurl || + (this.Ownerurl != null && + this.Ownerurl.Equals(input.Ownerurl)) + ); + } + + /// + /// Gets the hash code + /// + /// Hash code + public override int GetHashCode() + { + unchecked // Overflow is fine, just wrap + { + int hashCode = 41; + if (this.Id != null) + { + hashCode = (hashCode * 59) + this.Id.GetHashCode(); + } + if (this.Url != null) + { + hashCode = (hashCode * 59) + this.Url.GetHashCode(); + } + if (this.Formats != null) + { + hashCode = (hashCode * 59) + this.Formats.GetHashCode(); + } + if (this.Name != null) + { + hashCode = (hashCode * 59) + this.Name.GetHashCode(); + } + if (this.Description != null) + { + hashCode = (hashCode * 59) + this.Description.GetHashCode(); + } + if (this.Owner != null) + { + hashCode = (hashCode * 59) + this.Owner.GetHashCode(); + } + if (this.Visibility != null) + { + hashCode = (hashCode * 59) + this.Visibility.GetHashCode(); + } + hashCode = (hashCode * 59) + this.Curated.GetHashCode(); + if (this.Polyid != null) + { + hashCode = (hashCode * 59) + this.Polyid.GetHashCode(); + } + if (this.Polydata != null) + { + hashCode = (hashCode * 59) + this.Polydata.GetHashCode(); + } + if (this.Thumbnail != null) + { + hashCode = (hashCode * 59) + this.Thumbnail.GetHashCode(); + } + if (this.Ownername != null) + { + hashCode = (hashCode * 59) + this.Ownername.GetHashCode(); + } + if (this.Ownerurl != null) + { + hashCode = (hashCode * 59) + this.Ownerurl.GetHashCode(); + } + return hashCode; + } + } + + } + +} diff --git a/Assets/ThirdParty/Org.OpenAPITools/Model/Asset.cs.meta b/Assets/ThirdParty/Org.OpenAPITools/Model/Asset.cs.meta new file mode 100644 index 0000000000..c36f6c6485 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Model/Asset.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 13903908a3a4649ac8c5cb47853e1115 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThirdParty/Org.OpenAPITools/Model/AssetFormat.cs b/Assets/ThirdParty/Org.OpenAPITools/Model/AssetFormat.cs new file mode 100644 index 0000000000..9edef41c58 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Model/AssetFormat.cs @@ -0,0 +1,193 @@ +/* + * Icosa API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 0.1.0 + * Generated by: https://github.com/openapitools/openapi-generator.git + */ + + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.IO; +using System.Runtime.Serialization; +using System.Text; +using System.Text.RegularExpressions; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using Newtonsoft.Json.Linq; +using OpenAPIDateConverter = Org.OpenAPITools.Client.OpenAPIDateConverter; + +namespace Org.OpenAPITools.Model +{ + /// + /// AssetFormat + /// + [DataContract(Name = "AssetFormat")] + public partial class AssetFormat : IEquatable + { + /// + /// Initializes a new instance of the class. + /// + [JsonConstructorAttribute] + protected AssetFormat() { } + /// + /// Initializes a new instance of the class. + /// + /// id (required). + /// url (required). + /// format (required). + /// subfiles. + public AssetFormat(string id = default(string), string url = default(string), string format = default(string), List subfiles = default(List)) + { + // to ensure "id" is required (not null) + if (id == null) + { + throw new ArgumentNullException("id is a required property for AssetFormat and cannot be null"); + } + this.Id = id; + // to ensure "url" is required (not null) + if (url == null) + { + throw new ArgumentNullException("url is a required property for AssetFormat and cannot be null"); + } + this.Url = url; + // to ensure "format" is required (not null) + if (format == null) + { + throw new ArgumentNullException("format is a required property for AssetFormat and cannot be null"); + } + this.Format = format; + this.Subfiles = subfiles; + } + + /// + /// Gets or Sets Id + /// + [DataMember(Name = "id", IsRequired = true, EmitDefaultValue = true)] + public string Id { get; set; } + + /// + /// Gets or Sets Url + /// + [DataMember(Name = "url", IsRequired = true, EmitDefaultValue = true)] + public string Url { get; set; } + + /// + /// Gets or Sets Format + /// + [DataMember(Name = "format", IsRequired = true, EmitDefaultValue = true)] + public string Format { get; set; } + + /// + /// Gets or Sets Subfiles + /// + [DataMember(Name = "subfiles", EmitDefaultValue = false)] + public List Subfiles { get; set; } + + /// + /// Returns the string presentation of the object + /// + /// String presentation of the object + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + sb.Append("class AssetFormat {\n"); + sb.Append(" Id: ").Append(Id).Append("\n"); + sb.Append(" Url: ").Append(Url).Append("\n"); + sb.Append(" Format: ").Append(Format).Append("\n"); + sb.Append(" Subfiles: ").Append(Subfiles).Append("\n"); + sb.Append("}\n"); + return sb.ToString(); + } + + /// + /// Returns the JSON string presentation of the object + /// + /// JSON string presentation of the object + public virtual string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented); + } + + /// + /// Returns true if objects are equal + /// + /// Object to be compared + /// Boolean + public override bool Equals(object input) + { + return this.Equals(input as AssetFormat); + } + + /// + /// Returns true if AssetFormat instances are equal + /// + /// Instance of AssetFormat to be compared + /// Boolean + public bool Equals(AssetFormat input) + { + if (input == null) + { + return false; + } + return + ( + this.Id == input.Id || + (this.Id != null && + this.Id.Equals(input.Id)) + ) && + ( + this.Url == input.Url || + (this.Url != null && + this.Url.Equals(input.Url)) + ) && + ( + this.Format == input.Format || + (this.Format != null && + this.Format.Equals(input.Format)) + ) && + ( + this.Subfiles == input.Subfiles || + this.Subfiles != null && + input.Subfiles != null && + this.Subfiles.SequenceEqual(input.Subfiles) + ); + } + + /// + /// Gets the hash code + /// + /// Hash code + public override int GetHashCode() + { + unchecked // Overflow is fine, just wrap + { + int hashCode = 41; + if (this.Id != null) + { + hashCode = (hashCode * 59) + this.Id.GetHashCode(); + } + if (this.Url != null) + { + hashCode = (hashCode * 59) + this.Url.GetHashCode(); + } + if (this.Format != null) + { + hashCode = (hashCode * 59) + this.Format.GetHashCode(); + } + if (this.Subfiles != null) + { + hashCode = (hashCode * 59) + this.Subfiles.GetHashCode(); + } + return hashCode; + } + } + + } + +} diff --git a/Assets/ThirdParty/Org.OpenAPITools/Model/AssetFormat.cs.meta b/Assets/ThirdParty/Org.OpenAPITools/Model/AssetFormat.cs.meta new file mode 100644 index 0000000000..a4adb2a52f --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Model/AssetFormat.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a8754ff7004224003813d212e74a8510 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThirdParty/Org.OpenAPITools/Model/AssetPatchData.cs b/Assets/ThirdParty/Org.OpenAPITools/Model/AssetPatchData.cs new file mode 100644 index 0000000000..6e9e23e76b --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Model/AssetPatchData.cs @@ -0,0 +1,172 @@ +/* + * Icosa API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 0.1.0 + * Generated by: https://github.com/openapitools/openapi-generator.git + */ + + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.IO; +using System.Runtime.Serialization; +using System.Text; +using System.Text.RegularExpressions; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using Newtonsoft.Json.Linq; +using OpenAPIDateConverter = Org.OpenAPITools.Client.OpenAPIDateConverter; + +namespace Org.OpenAPITools.Model +{ + /// + /// AssetPatchData + /// + [DataContract(Name = "AssetPatchData")] + public partial class AssetPatchData : IEquatable + { + /// + /// Initializes a new instance of the class. + /// + /// name. + /// url. + /// description. + /// visibility. + public AssetPatchData(string name = default(string), string url = default(string), string description = default(string), string visibility = default(string)) + { + this.Name = name; + this.Url = url; + this.Description = description; + this.Visibility = visibility; + } + + /// + /// Gets or Sets Name + /// + [DataMember(Name = "name", EmitDefaultValue = false)] + public string Name { get; set; } + + /// + /// Gets or Sets Url + /// + [DataMember(Name = "url", EmitDefaultValue = false)] + public string Url { get; set; } + + /// + /// Gets or Sets Description + /// + [DataMember(Name = "description", EmitDefaultValue = false)] + public string Description { get; set; } + + /// + /// Gets or Sets Visibility + /// + [DataMember(Name = "visibility", EmitDefaultValue = false)] + public string Visibility { get; set; } + + /// + /// Returns the string presentation of the object + /// + /// String presentation of the object + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + sb.Append("class AssetPatchData {\n"); + sb.Append(" Name: ").Append(Name).Append("\n"); + sb.Append(" Url: ").Append(Url).Append("\n"); + sb.Append(" Description: ").Append(Description).Append("\n"); + sb.Append(" Visibility: ").Append(Visibility).Append("\n"); + sb.Append("}\n"); + return sb.ToString(); + } + + /// + /// Returns the JSON string presentation of the object + /// + /// JSON string presentation of the object + public virtual string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented); + } + + /// + /// Returns true if objects are equal + /// + /// Object to be compared + /// Boolean + public override bool Equals(object input) + { + return this.Equals(input as AssetPatchData); + } + + /// + /// Returns true if AssetPatchData instances are equal + /// + /// Instance of AssetPatchData to be compared + /// Boolean + public bool Equals(AssetPatchData input) + { + if (input == null) + { + return false; + } + return + ( + this.Name == input.Name || + (this.Name != null && + this.Name.Equals(input.Name)) + ) && + ( + this.Url == input.Url || + (this.Url != null && + this.Url.Equals(input.Url)) + ) && + ( + this.Description == input.Description || + (this.Description != null && + this.Description.Equals(input.Description)) + ) && + ( + this.Visibility == input.Visibility || + (this.Visibility != null && + this.Visibility.Equals(input.Visibility)) + ); + } + + /// + /// Gets the hash code + /// + /// Hash code + public override int GetHashCode() + { + unchecked // Overflow is fine, just wrap + { + int hashCode = 41; + if (this.Name != null) + { + hashCode = (hashCode * 59) + this.Name.GetHashCode(); + } + if (this.Url != null) + { + hashCode = (hashCode * 59) + this.Url.GetHashCode(); + } + if (this.Description != null) + { + hashCode = (hashCode * 59) + this.Description.GetHashCode(); + } + if (this.Visibility != null) + { + hashCode = (hashCode * 59) + this.Visibility.GetHashCode(); + } + return hashCode; + } + } + + } + +} diff --git a/Assets/ThirdParty/Org.OpenAPITools/Model/AssetPatchData.cs.meta b/Assets/ThirdParty/Org.OpenAPITools/Model/AssetPatchData.cs.meta new file mode 100644 index 0000000000..837ee104f6 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Model/AssetPatchData.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e55da885c6d2b49549afd61e0670026f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThirdParty/Org.OpenAPITools/Model/DeviceCode.cs b/Assets/ThirdParty/Org.OpenAPITools/Model/DeviceCode.cs new file mode 100644 index 0000000000..01eb19b9fd --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Model/DeviceCode.cs @@ -0,0 +1,128 @@ +/* + * Icosa API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 0.1.0 + * Generated by: https://github.com/openapitools/openapi-generator.git + */ + + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.IO; +using System.Runtime.Serialization; +using System.Text; +using System.Text.RegularExpressions; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using Newtonsoft.Json.Linq; +using OpenAPIDateConverter = Org.OpenAPITools.Client.OpenAPIDateConverter; + +namespace Org.OpenAPITools.Model +{ + /// + /// DeviceCode + /// + [DataContract(Name = "DeviceCode")] + public partial class DeviceCode : IEquatable + { + /// + /// Initializes a new instance of the class. + /// + [JsonConstructorAttribute] + protected DeviceCode() { } + /// + /// Initializes a new instance of the class. + /// + /// varDeviceCode (required). + public DeviceCode(string varDeviceCode = default(string)) + { + // to ensure "varDeviceCode" is required (not null) + if (varDeviceCode == null) + { + throw new ArgumentNullException("varDeviceCode is a required property for DeviceCode and cannot be null"); + } + this.VarDeviceCode = varDeviceCode; + } + + /// + /// Gets or Sets VarDeviceCode + /// + [DataMember(Name = "deviceCode", IsRequired = true, EmitDefaultValue = true)] + public string VarDeviceCode { get; set; } + + /// + /// Returns the string presentation of the object + /// + /// String presentation of the object + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + sb.Append("class DeviceCode {\n"); + sb.Append(" VarDeviceCode: ").Append(VarDeviceCode).Append("\n"); + sb.Append("}\n"); + return sb.ToString(); + } + + /// + /// Returns the JSON string presentation of the object + /// + /// JSON string presentation of the object + public virtual string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented); + } + + /// + /// Returns true if objects are equal + /// + /// Object to be compared + /// Boolean + public override bool Equals(object input) + { + return this.Equals(input as DeviceCode); + } + + /// + /// Returns true if DeviceCode instances are equal + /// + /// Instance of DeviceCode to be compared + /// Boolean + public bool Equals(DeviceCode input) + { + if (input == null) + { + return false; + } + return + ( + this.VarDeviceCode == input.VarDeviceCode || + (this.VarDeviceCode != null && + this.VarDeviceCode.Equals(input.VarDeviceCode)) + ); + } + + /// + /// Gets the hash code + /// + /// Hash code + public override int GetHashCode() + { + unchecked // Overflow is fine, just wrap + { + int hashCode = 41; + if (this.VarDeviceCode != null) + { + hashCode = (hashCode * 59) + this.VarDeviceCode.GetHashCode(); + } + return hashCode; + } + } + + } + +} diff --git a/Assets/ThirdParty/Org.OpenAPITools/Model/DeviceCode.cs.meta b/Assets/ThirdParty/Org.OpenAPITools/Model/DeviceCode.cs.meta new file mode 100644 index 0000000000..31f77abbe7 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Model/DeviceCode.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a2f16d6e33569435d9b4e19f51b62e70 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThirdParty/Org.OpenAPITools/Model/EmailChangeAuthenticated.cs b/Assets/ThirdParty/Org.OpenAPITools/Model/EmailChangeAuthenticated.cs new file mode 100644 index 0000000000..0ebb01113b --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Model/EmailChangeAuthenticated.cs @@ -0,0 +1,151 @@ +/* + * Icosa API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 0.1.0 + * Generated by: https://github.com/openapitools/openapi-generator.git + */ + + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.IO; +using System.Runtime.Serialization; +using System.Text; +using System.Text.RegularExpressions; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using Newtonsoft.Json.Linq; +using OpenAPIDateConverter = Org.OpenAPITools.Client.OpenAPIDateConverter; + +namespace Org.OpenAPITools.Model +{ + /// + /// EmailChangeAuthenticated + /// + [DataContract(Name = "EmailChangeAuthenticated")] + public partial class EmailChangeAuthenticated : IEquatable + { + /// + /// Initializes a new instance of the class. + /// + [JsonConstructorAttribute] + protected EmailChangeAuthenticated() { } + /// + /// Initializes a new instance of the class. + /// + /// newEmail (required). + /// currentPassword (required). + public EmailChangeAuthenticated(string newEmail = default(string), string currentPassword = default(string)) + { + // to ensure "newEmail" is required (not null) + if (newEmail == null) + { + throw new ArgumentNullException("newEmail is a required property for EmailChangeAuthenticated and cannot be null"); + } + this.NewEmail = newEmail; + // to ensure "currentPassword" is required (not null) + if (currentPassword == null) + { + throw new ArgumentNullException("currentPassword is a required property for EmailChangeAuthenticated and cannot be null"); + } + this.CurrentPassword = currentPassword; + } + + /// + /// Gets or Sets NewEmail + /// + [DataMember(Name = "newEmail", IsRequired = true, EmitDefaultValue = true)] + public string NewEmail { get; set; } + + /// + /// Gets or Sets CurrentPassword + /// + [DataMember(Name = "currentPassword", IsRequired = true, EmitDefaultValue = true)] + public string CurrentPassword { get; set; } + + /// + /// Returns the string presentation of the object + /// + /// String presentation of the object + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + sb.Append("class EmailChangeAuthenticated {\n"); + sb.Append(" NewEmail: ").Append(NewEmail).Append("\n"); + sb.Append(" CurrentPassword: ").Append(CurrentPassword).Append("\n"); + sb.Append("}\n"); + return sb.ToString(); + } + + /// + /// Returns the JSON string presentation of the object + /// + /// JSON string presentation of the object + public virtual string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented); + } + + /// + /// Returns true if objects are equal + /// + /// Object to be compared + /// Boolean + public override bool Equals(object input) + { + return this.Equals(input as EmailChangeAuthenticated); + } + + /// + /// Returns true if EmailChangeAuthenticated instances are equal + /// + /// Instance of EmailChangeAuthenticated to be compared + /// Boolean + public bool Equals(EmailChangeAuthenticated input) + { + if (input == null) + { + return false; + } + return + ( + this.NewEmail == input.NewEmail || + (this.NewEmail != null && + this.NewEmail.Equals(input.NewEmail)) + ) && + ( + this.CurrentPassword == input.CurrentPassword || + (this.CurrentPassword != null && + this.CurrentPassword.Equals(input.CurrentPassword)) + ); + } + + /// + /// Gets the hash code + /// + /// Hash code + public override int GetHashCode() + { + unchecked // Overflow is fine, just wrap + { + int hashCode = 41; + if (this.NewEmail != null) + { + hashCode = (hashCode * 59) + this.NewEmail.GetHashCode(); + } + if (this.CurrentPassword != null) + { + hashCode = (hashCode * 59) + this.CurrentPassword.GetHashCode(); + } + return hashCode; + } + } + + } + +} diff --git a/Assets/ThirdParty/Org.OpenAPITools/Model/EmailChangeAuthenticated.cs.meta b/Assets/ThirdParty/Org.OpenAPITools/Model/EmailChangeAuthenticated.cs.meta new file mode 100644 index 0000000000..fd20d7531d --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Model/EmailChangeAuthenticated.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6cbeb403da2584de4a1971e3daf03016 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThirdParty/Org.OpenAPITools/Model/FullUser.cs b/Assets/ThirdParty/Org.OpenAPITools/Model/FullUser.cs new file mode 100644 index 0000000000..b71a094ba0 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Model/FullUser.cs @@ -0,0 +1,215 @@ +/* + * Icosa API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 0.1.0 + * Generated by: https://github.com/openapitools/openapi-generator.git + */ + + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.IO; +using System.Runtime.Serialization; +using System.Text; +using System.Text.RegularExpressions; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using Newtonsoft.Json.Linq; +using OpenAPIDateConverter = Org.OpenAPITools.Client.OpenAPIDateConverter; + +namespace Org.OpenAPITools.Model +{ + /// + /// FullUser + /// + [DataContract(Name = "FullUser")] + public partial class FullUser : IEquatable + { + /// + /// Initializes a new instance of the class. + /// + [JsonConstructorAttribute] + protected FullUser() { } + /// + /// Initializes a new instance of the class. + /// + /// id (required). + /// url (required). + /// email (required). + /// displayname (required). + /// description. + public FullUser(string id = default(string), string url = default(string), string email = default(string), string displayname = default(string), string description = default(string)) + { + // to ensure "id" is required (not null) + if (id == null) + { + throw new ArgumentNullException("id is a required property for FullUser and cannot be null"); + } + this.Id = id; + // to ensure "url" is required (not null) + if (url == null) + { + throw new ArgumentNullException("url is a required property for FullUser and cannot be null"); + } + this.Url = url; + // to ensure "email" is required (not null) + if (email == null) + { + throw new ArgumentNullException("email is a required property for FullUser and cannot be null"); + } + this.Email = email; + // to ensure "displayname" is required (not null) + if (displayname == null) + { + throw new ArgumentNullException("displayname is a required property for FullUser and cannot be null"); + } + this.Displayname = displayname; + this.Description = description; + } + + /// + /// Gets or Sets Id + /// + [DataMember(Name = "id", IsRequired = true, EmitDefaultValue = true)] + public string Id { get; set; } + + /// + /// Gets or Sets Url + /// + [DataMember(Name = "url", IsRequired = true, EmitDefaultValue = true)] + public string Url { get; set; } + + /// + /// Gets or Sets Email + /// + [DataMember(Name = "email", IsRequired = true, EmitDefaultValue = true)] + public string Email { get; set; } + + /// + /// Gets or Sets Displayname + /// + [DataMember(Name = "displayname", IsRequired = true, EmitDefaultValue = true)] + public string Displayname { get; set; } + + /// + /// Gets or Sets Description + /// + [DataMember(Name = "description", EmitDefaultValue = false)] + public string Description { get; set; } + + /// + /// Returns the string presentation of the object + /// + /// String presentation of the object + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + sb.Append("class FullUser {\n"); + sb.Append(" Id: ").Append(Id).Append("\n"); + sb.Append(" Url: ").Append(Url).Append("\n"); + sb.Append(" Email: ").Append(Email).Append("\n"); + sb.Append(" Displayname: ").Append(Displayname).Append("\n"); + sb.Append(" Description: ").Append(Description).Append("\n"); + sb.Append("}\n"); + return sb.ToString(); + } + + /// + /// Returns the JSON string presentation of the object + /// + /// JSON string presentation of the object + public virtual string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented); + } + + /// + /// Returns true if objects are equal + /// + /// Object to be compared + /// Boolean + public override bool Equals(object input) + { + return this.Equals(input as FullUser); + } + + /// + /// Returns true if FullUser instances are equal + /// + /// Instance of FullUser to be compared + /// Boolean + public bool Equals(FullUser input) + { + if (input == null) + { + return false; + } + return + ( + this.Id == input.Id || + (this.Id != null && + this.Id.Equals(input.Id)) + ) && + ( + this.Url == input.Url || + (this.Url != null && + this.Url.Equals(input.Url)) + ) && + ( + this.Email == input.Email || + (this.Email != null && + this.Email.Equals(input.Email)) + ) && + ( + this.Displayname == input.Displayname || + (this.Displayname != null && + this.Displayname.Equals(input.Displayname)) + ) && + ( + this.Description == input.Description || + (this.Description != null && + this.Description.Equals(input.Description)) + ); + } + + /// + /// Gets the hash code + /// + /// Hash code + public override int GetHashCode() + { + unchecked // Overflow is fine, just wrap + { + int hashCode = 41; + if (this.Id != null) + { + hashCode = (hashCode * 59) + this.Id.GetHashCode(); + } + if (this.Url != null) + { + hashCode = (hashCode * 59) + this.Url.GetHashCode(); + } + if (this.Email != null) + { + hashCode = (hashCode * 59) + this.Email.GetHashCode(); + } + if (this.Displayname != null) + { + hashCode = (hashCode * 59) + this.Displayname.GetHashCode(); + } + if (this.Description != null) + { + hashCode = (hashCode * 59) + this.Description.GetHashCode(); + } + return hashCode; + } + } + + } + +} diff --git a/Assets/ThirdParty/Org.OpenAPITools/Model/FullUser.cs.meta b/Assets/ThirdParty/Org.OpenAPITools/Model/FullUser.cs.meta new file mode 100644 index 0000000000..6f2c889e6d --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Model/FullUser.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e1d4b242588d04df5bf461d74f47d8c6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThirdParty/Org.OpenAPITools/Model/HTTPValidationError.cs b/Assets/ThirdParty/Org.OpenAPITools/Model/HTTPValidationError.cs new file mode 100644 index 0000000000..5648a358d7 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Model/HTTPValidationError.cs @@ -0,0 +1,119 @@ +/* + * Icosa API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 0.1.0 + * Generated by: https://github.com/openapitools/openapi-generator.git + */ + + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.IO; +using System.Runtime.Serialization; +using System.Text; +using System.Text.RegularExpressions; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using Newtonsoft.Json.Linq; +using OpenAPIDateConverter = Org.OpenAPITools.Client.OpenAPIDateConverter; + +namespace Org.OpenAPITools.Model +{ + /// + /// HTTPValidationError + /// + [DataContract(Name = "HTTPValidationError")] + public partial class HTTPValidationError : IEquatable + { + /// + /// Initializes a new instance of the class. + /// + /// detail. + public HTTPValidationError(List detail = default(List)) + { + this.Detail = detail; + } + + /// + /// Gets or Sets Detail + /// + [DataMember(Name = "detail", EmitDefaultValue = false)] + public List Detail { get; set; } + + /// + /// Returns the string presentation of the object + /// + /// String presentation of the object + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + sb.Append("class HTTPValidationError {\n"); + sb.Append(" Detail: ").Append(Detail).Append("\n"); + sb.Append("}\n"); + return sb.ToString(); + } + + /// + /// Returns the JSON string presentation of the object + /// + /// JSON string presentation of the object + public virtual string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented); + } + + /// + /// Returns true if objects are equal + /// + /// Object to be compared + /// Boolean + public override bool Equals(object input) + { + return this.Equals(input as HTTPValidationError); + } + + /// + /// Returns true if HTTPValidationError instances are equal + /// + /// Instance of HTTPValidationError to be compared + /// Boolean + public bool Equals(HTTPValidationError input) + { + if (input == null) + { + return false; + } + return + ( + this.Detail == input.Detail || + this.Detail != null && + input.Detail != null && + this.Detail.SequenceEqual(input.Detail) + ); + } + + /// + /// Gets the hash code + /// + /// Hash code + public override int GetHashCode() + { + unchecked // Overflow is fine, just wrap + { + int hashCode = 41; + if (this.Detail != null) + { + hashCode = (hashCode * 59) + this.Detail.GetHashCode(); + } + return hashCode; + } + } + + } + +} diff --git a/Assets/ThirdParty/Org.OpenAPITools/Model/HTTPValidationError.cs.meta b/Assets/ThirdParty/Org.OpenAPITools/Model/HTTPValidationError.cs.meta new file mode 100644 index 0000000000..528ca2f0a5 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Model/HTTPValidationError.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c84cf1dcd613a479ab8ad6f98d82c55e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThirdParty/Org.OpenAPITools/Model/LoginToken.cs b/Assets/ThirdParty/Org.OpenAPITools/Model/LoginToken.cs new file mode 100644 index 0000000000..24f20f75bf --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Model/LoginToken.cs @@ -0,0 +1,151 @@ +/* + * Icosa API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 0.1.0 + * Generated by: https://github.com/openapitools/openapi-generator.git + */ + + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.IO; +using System.Runtime.Serialization; +using System.Text; +using System.Text.RegularExpressions; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using Newtonsoft.Json.Linq; +using OpenAPIDateConverter = Org.OpenAPITools.Client.OpenAPIDateConverter; + +namespace Org.OpenAPITools.Model +{ + /// + /// LoginToken + /// + [DataContract(Name = "LoginToken")] + public partial class LoginToken : IEquatable + { + /// + /// Initializes a new instance of the class. + /// + [JsonConstructorAttribute] + protected LoginToken() { } + /// + /// Initializes a new instance of the class. + /// + /// accessToken (required). + /// tokenType (required). + public LoginToken(string accessToken = default(string), string tokenType = default(string)) + { + // to ensure "accessToken" is required (not null) + if (accessToken == null) + { + throw new ArgumentNullException("accessToken is a required property for LoginToken and cannot be null"); + } + this.AccessToken = accessToken; + // to ensure "tokenType" is required (not null) + if (tokenType == null) + { + throw new ArgumentNullException("tokenType is a required property for LoginToken and cannot be null"); + } + this.TokenType = tokenType; + } + + /// + /// Gets or Sets AccessToken + /// + [DataMember(Name = "access_token", IsRequired = true, EmitDefaultValue = true)] + public string AccessToken { get; set; } + + /// + /// Gets or Sets TokenType + /// + [DataMember(Name = "token_type", IsRequired = true, EmitDefaultValue = true)] + public string TokenType { get; set; } + + /// + /// Returns the string presentation of the object + /// + /// String presentation of the object + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + sb.Append("class LoginToken {\n"); + sb.Append(" AccessToken: ").Append(AccessToken).Append("\n"); + sb.Append(" TokenType: ").Append(TokenType).Append("\n"); + sb.Append("}\n"); + return sb.ToString(); + } + + /// + /// Returns the JSON string presentation of the object + /// + /// JSON string presentation of the object + public virtual string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented); + } + + /// + /// Returns true if objects are equal + /// + /// Object to be compared + /// Boolean + public override bool Equals(object input) + { + return this.Equals(input as LoginToken); + } + + /// + /// Returns true if LoginToken instances are equal + /// + /// Instance of LoginToken to be compared + /// Boolean + public bool Equals(LoginToken input) + { + if (input == null) + { + return false; + } + return + ( + this.AccessToken == input.AccessToken || + (this.AccessToken != null && + this.AccessToken.Equals(input.AccessToken)) + ) && + ( + this.TokenType == input.TokenType || + (this.TokenType != null && + this.TokenType.Equals(input.TokenType)) + ); + } + + /// + /// Gets the hash code + /// + /// Hash code + public override int GetHashCode() + { + unchecked // Overflow is fine, just wrap + { + int hashCode = 41; + if (this.AccessToken != null) + { + hashCode = (hashCode * 59) + this.AccessToken.GetHashCode(); + } + if (this.TokenType != null) + { + hashCode = (hashCode * 59) + this.TokenType.GetHashCode(); + } + return hashCode; + } + } + + } + +} diff --git a/Assets/ThirdParty/Org.OpenAPITools/Model/LoginToken.cs.meta b/Assets/ThirdParty/Org.OpenAPITools/Model/LoginToken.cs.meta new file mode 100644 index 0000000000..e5779e1e6d --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Model/LoginToken.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f7270badae5584c779dc43a1277073d8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThirdParty/Org.OpenAPITools/Model/NewUser.cs b/Assets/ThirdParty/Org.OpenAPITools/Model/NewUser.cs new file mode 100644 index 0000000000..75b56abe8f --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Model/NewUser.cs @@ -0,0 +1,192 @@ +/* + * Icosa API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 0.1.0 + * Generated by: https://github.com/openapitools/openapi-generator.git + */ + + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.IO; +using System.Runtime.Serialization; +using System.Text; +using System.Text.RegularExpressions; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using Newtonsoft.Json.Linq; +using OpenAPIDateConverter = Org.OpenAPITools.Client.OpenAPIDateConverter; + +namespace Org.OpenAPITools.Model +{ + /// + /// NewUser + /// + [DataContract(Name = "NewUser")] + public partial class NewUser : IEquatable + { + /// + /// Initializes a new instance of the class. + /// + [JsonConstructorAttribute] + protected NewUser() { } + /// + /// Initializes a new instance of the class. + /// + /// email (required). + /// url. + /// password (required). + /// displayName (required). + public NewUser(string email = default(string), string url = default(string), string password = default(string), string displayName = default(string)) + { + // to ensure "email" is required (not null) + if (email == null) + { + throw new ArgumentNullException("email is a required property for NewUser and cannot be null"); + } + this.Email = email; + // to ensure "password" is required (not null) + if (password == null) + { + throw new ArgumentNullException("password is a required property for NewUser and cannot be null"); + } + this.Password = password; + // to ensure "displayName" is required (not null) + if (displayName == null) + { + throw new ArgumentNullException("displayName is a required property for NewUser and cannot be null"); + } + this.DisplayName = displayName; + this.Url = url; + } + + /// + /// Gets or Sets Email + /// + [DataMember(Name = "email", IsRequired = true, EmitDefaultValue = true)] + public string Email { get; set; } + + /// + /// Gets or Sets Url + /// + [DataMember(Name = "url", EmitDefaultValue = false)] + public string Url { get; set; } + + /// + /// Gets or Sets Password + /// + [DataMember(Name = "password", IsRequired = true, EmitDefaultValue = true)] + public string Password { get; set; } + + /// + /// Gets or Sets DisplayName + /// + [DataMember(Name = "displayName", IsRequired = true, EmitDefaultValue = true)] + public string DisplayName { get; set; } + + /// + /// Returns the string presentation of the object + /// + /// String presentation of the object + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + sb.Append("class NewUser {\n"); + sb.Append(" Email: ").Append(Email).Append("\n"); + sb.Append(" Url: ").Append(Url).Append("\n"); + sb.Append(" Password: ").Append(Password).Append("\n"); + sb.Append(" DisplayName: ").Append(DisplayName).Append("\n"); + sb.Append("}\n"); + return sb.ToString(); + } + + /// + /// Returns the JSON string presentation of the object + /// + /// JSON string presentation of the object + public virtual string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented); + } + + /// + /// Returns true if objects are equal + /// + /// Object to be compared + /// Boolean + public override bool Equals(object input) + { + return this.Equals(input as NewUser); + } + + /// + /// Returns true if NewUser instances are equal + /// + /// Instance of NewUser to be compared + /// Boolean + public bool Equals(NewUser input) + { + if (input == null) + { + return false; + } + return + ( + this.Email == input.Email || + (this.Email != null && + this.Email.Equals(input.Email)) + ) && + ( + this.Url == input.Url || + (this.Url != null && + this.Url.Equals(input.Url)) + ) && + ( + this.Password == input.Password || + (this.Password != null && + this.Password.Equals(input.Password)) + ) && + ( + this.DisplayName == input.DisplayName || + (this.DisplayName != null && + this.DisplayName.Equals(input.DisplayName)) + ); + } + + /// + /// Gets the hash code + /// + /// Hash code + public override int GetHashCode() + { + unchecked // Overflow is fine, just wrap + { + int hashCode = 41; + if (this.Email != null) + { + hashCode = (hashCode * 59) + this.Email.GetHashCode(); + } + if (this.Url != null) + { + hashCode = (hashCode * 59) + this.Url.GetHashCode(); + } + if (this.Password != null) + { + hashCode = (hashCode * 59) + this.Password.GetHashCode(); + } + if (this.DisplayName != null) + { + hashCode = (hashCode * 59) + this.DisplayName.GetHashCode(); + } + return hashCode; + } + } + + } + +} diff --git a/Assets/ThirdParty/Org.OpenAPITools/Model/NewUser.cs.meta b/Assets/ThirdParty/Org.OpenAPITools/Model/NewUser.cs.meta new file mode 100644 index 0000000000..22eaf463a0 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Model/NewUser.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 75d47b85fa7d74e7abcbb9c0329757c7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThirdParty/Org.OpenAPITools/Model/PasswordChangeAuthenticated.cs b/Assets/ThirdParty/Org.OpenAPITools/Model/PasswordChangeAuthenticated.cs new file mode 100644 index 0000000000..1eb4bc0c97 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Model/PasswordChangeAuthenticated.cs @@ -0,0 +1,151 @@ +/* + * Icosa API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 0.1.0 + * Generated by: https://github.com/openapitools/openapi-generator.git + */ + + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.IO; +using System.Runtime.Serialization; +using System.Text; +using System.Text.RegularExpressions; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using Newtonsoft.Json.Linq; +using OpenAPIDateConverter = Org.OpenAPITools.Client.OpenAPIDateConverter; + +namespace Org.OpenAPITools.Model +{ + /// + /// PasswordChangeAuthenticated + /// + [DataContract(Name = "PasswordChangeAuthenticated")] + public partial class PasswordChangeAuthenticated : IEquatable + { + /// + /// Initializes a new instance of the class. + /// + [JsonConstructorAttribute] + protected PasswordChangeAuthenticated() { } + /// + /// Initializes a new instance of the class. + /// + /// oldPassword (required). + /// newPassword (required). + public PasswordChangeAuthenticated(string oldPassword = default(string), string newPassword = default(string)) + { + // to ensure "oldPassword" is required (not null) + if (oldPassword == null) + { + throw new ArgumentNullException("oldPassword is a required property for PasswordChangeAuthenticated and cannot be null"); + } + this.OldPassword = oldPassword; + // to ensure "newPassword" is required (not null) + if (newPassword == null) + { + throw new ArgumentNullException("newPassword is a required property for PasswordChangeAuthenticated and cannot be null"); + } + this.NewPassword = newPassword; + } + + /// + /// Gets or Sets OldPassword + /// + [DataMember(Name = "oldPassword", IsRequired = true, EmitDefaultValue = true)] + public string OldPassword { get; set; } + + /// + /// Gets or Sets NewPassword + /// + [DataMember(Name = "newPassword", IsRequired = true, EmitDefaultValue = true)] + public string NewPassword { get; set; } + + /// + /// Returns the string presentation of the object + /// + /// String presentation of the object + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + sb.Append("class PasswordChangeAuthenticated {\n"); + sb.Append(" OldPassword: ").Append(OldPassword).Append("\n"); + sb.Append(" NewPassword: ").Append(NewPassword).Append("\n"); + sb.Append("}\n"); + return sb.ToString(); + } + + /// + /// Returns the JSON string presentation of the object + /// + /// JSON string presentation of the object + public virtual string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented); + } + + /// + /// Returns true if objects are equal + /// + /// Object to be compared + /// Boolean + public override bool Equals(object input) + { + return this.Equals(input as PasswordChangeAuthenticated); + } + + /// + /// Returns true if PasswordChangeAuthenticated instances are equal + /// + /// Instance of PasswordChangeAuthenticated to be compared + /// Boolean + public bool Equals(PasswordChangeAuthenticated input) + { + if (input == null) + { + return false; + } + return + ( + this.OldPassword == input.OldPassword || + (this.OldPassword != null && + this.OldPassword.Equals(input.OldPassword)) + ) && + ( + this.NewPassword == input.NewPassword || + (this.NewPassword != null && + this.NewPassword.Equals(input.NewPassword)) + ); + } + + /// + /// Gets the hash code + /// + /// Hash code + public override int GetHashCode() + { + unchecked // Overflow is fine, just wrap + { + int hashCode = 41; + if (this.OldPassword != null) + { + hashCode = (hashCode * 59) + this.OldPassword.GetHashCode(); + } + if (this.NewPassword != null) + { + hashCode = (hashCode * 59) + this.NewPassword.GetHashCode(); + } + return hashCode; + } + } + + } + +} diff --git a/Assets/ThirdParty/Org.OpenAPITools/Model/PasswordChangeAuthenticated.cs.meta b/Assets/ThirdParty/Org.OpenAPITools/Model/PasswordChangeAuthenticated.cs.meta new file mode 100644 index 0000000000..e52415b387 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Model/PasswordChangeAuthenticated.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 29519200cd400434b929afcc7e0b9ffb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThirdParty/Org.OpenAPITools/Model/PasswordChangeToken.cs b/Assets/ThirdParty/Org.OpenAPITools/Model/PasswordChangeToken.cs new file mode 100644 index 0000000000..1f85af4eb2 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Model/PasswordChangeToken.cs @@ -0,0 +1,151 @@ +/* + * Icosa API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 0.1.0 + * Generated by: https://github.com/openapitools/openapi-generator.git + */ + + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.IO; +using System.Runtime.Serialization; +using System.Text; +using System.Text.RegularExpressions; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using Newtonsoft.Json.Linq; +using OpenAPIDateConverter = Org.OpenAPITools.Client.OpenAPIDateConverter; + +namespace Org.OpenAPITools.Model +{ + /// + /// PasswordChangeToken + /// + [DataContract(Name = "PasswordChangeToken")] + public partial class PasswordChangeToken : IEquatable + { + /// + /// Initializes a new instance of the class. + /// + [JsonConstructorAttribute] + protected PasswordChangeToken() { } + /// + /// Initializes a new instance of the class. + /// + /// token (required). + /// newPassword (required). + public PasswordChangeToken(string token = default(string), string newPassword = default(string)) + { + // to ensure "token" is required (not null) + if (token == null) + { + throw new ArgumentNullException("token is a required property for PasswordChangeToken and cannot be null"); + } + this.Token = token; + // to ensure "newPassword" is required (not null) + if (newPassword == null) + { + throw new ArgumentNullException("newPassword is a required property for PasswordChangeToken and cannot be null"); + } + this.NewPassword = newPassword; + } + + /// + /// Gets or Sets Token + /// + [DataMember(Name = "token", IsRequired = true, EmitDefaultValue = true)] + public string Token { get; set; } + + /// + /// Gets or Sets NewPassword + /// + [DataMember(Name = "newPassword", IsRequired = true, EmitDefaultValue = true)] + public string NewPassword { get; set; } + + /// + /// Returns the string presentation of the object + /// + /// String presentation of the object + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + sb.Append("class PasswordChangeToken {\n"); + sb.Append(" Token: ").Append(Token).Append("\n"); + sb.Append(" NewPassword: ").Append(NewPassword).Append("\n"); + sb.Append("}\n"); + return sb.ToString(); + } + + /// + /// Returns the JSON string presentation of the object + /// + /// JSON string presentation of the object + public virtual string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented); + } + + /// + /// Returns true if objects are equal + /// + /// Object to be compared + /// Boolean + public override bool Equals(object input) + { + return this.Equals(input as PasswordChangeToken); + } + + /// + /// Returns true if PasswordChangeToken instances are equal + /// + /// Instance of PasswordChangeToken to be compared + /// Boolean + public bool Equals(PasswordChangeToken input) + { + if (input == null) + { + return false; + } + return + ( + this.Token == input.Token || + (this.Token != null && + this.Token.Equals(input.Token)) + ) && + ( + this.NewPassword == input.NewPassword || + (this.NewPassword != null && + this.NewPassword.Equals(input.NewPassword)) + ); + } + + /// + /// Gets the hash code + /// + /// Hash code + public override int GetHashCode() + { + unchecked // Overflow is fine, just wrap + { + int hashCode = 41; + if (this.Token != null) + { + hashCode = (hashCode * 59) + this.Token.GetHashCode(); + } + if (this.NewPassword != null) + { + hashCode = (hashCode * 59) + this.NewPassword.GetHashCode(); + } + return hashCode; + } + } + + } + +} diff --git a/Assets/ThirdParty/Org.OpenAPITools/Model/PasswordChangeToken.cs.meta b/Assets/ThirdParty/Org.OpenAPITools/Model/PasswordChangeToken.cs.meta new file mode 100644 index 0000000000..2682fa9efc --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Model/PasswordChangeToken.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2c0694c4508a3401aa835b6a88a8a150 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThirdParty/Org.OpenAPITools/Model/PasswordReset.cs b/Assets/ThirdParty/Org.OpenAPITools/Model/PasswordReset.cs new file mode 100644 index 0000000000..0f1a8f7718 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Model/PasswordReset.cs @@ -0,0 +1,128 @@ +/* + * Icosa API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 0.1.0 + * Generated by: https://github.com/openapitools/openapi-generator.git + */ + + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.IO; +using System.Runtime.Serialization; +using System.Text; +using System.Text.RegularExpressions; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using Newtonsoft.Json.Linq; +using OpenAPIDateConverter = Org.OpenAPITools.Client.OpenAPIDateConverter; + +namespace Org.OpenAPITools.Model +{ + /// + /// PasswordReset + /// + [DataContract(Name = "PasswordReset")] + public partial class PasswordReset : IEquatable + { + /// + /// Initializes a new instance of the class. + /// + [JsonConstructorAttribute] + protected PasswordReset() { } + /// + /// Initializes a new instance of the class. + /// + /// email (required). + public PasswordReset(string email = default(string)) + { + // to ensure "email" is required (not null) + if (email == null) + { + throw new ArgumentNullException("email is a required property for PasswordReset and cannot be null"); + } + this.Email = email; + } + + /// + /// Gets or Sets Email + /// + [DataMember(Name = "email", IsRequired = true, EmitDefaultValue = true)] + public string Email { get; set; } + + /// + /// Returns the string presentation of the object + /// + /// String presentation of the object + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + sb.Append("class PasswordReset {\n"); + sb.Append(" Email: ").Append(Email).Append("\n"); + sb.Append("}\n"); + return sb.ToString(); + } + + /// + /// Returns the JSON string presentation of the object + /// + /// JSON string presentation of the object + public virtual string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented); + } + + /// + /// Returns true if objects are equal + /// + /// Object to be compared + /// Boolean + public override bool Equals(object input) + { + return this.Equals(input as PasswordReset); + } + + /// + /// Returns true if PasswordReset instances are equal + /// + /// Instance of PasswordReset to be compared + /// Boolean + public bool Equals(PasswordReset input) + { + if (input == null) + { + return false; + } + return + ( + this.Email == input.Email || + (this.Email != null && + this.Email.Equals(input.Email)) + ); + } + + /// + /// Gets the hash code + /// + /// Hash code + public override int GetHashCode() + { + unchecked // Overflow is fine, just wrap + { + int hashCode = 41; + if (this.Email != null) + { + hashCode = (hashCode * 59) + this.Email.GetHashCode(); + } + return hashCode; + } + } + + } + +} diff --git a/Assets/ThirdParty/Org.OpenAPITools/Model/PasswordReset.cs.meta b/Assets/ThirdParty/Org.OpenAPITools/Model/PasswordReset.cs.meta new file mode 100644 index 0000000000..38715a23e0 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Model/PasswordReset.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c5136e21ab95742d2b27b64ce2fa380a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThirdParty/Org.OpenAPITools/Model/PatchUser.cs b/Assets/ThirdParty/Org.OpenAPITools/Model/PatchUser.cs new file mode 100644 index 0000000000..9ceec3fc68 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Model/PatchUser.cs @@ -0,0 +1,154 @@ +/* + * Icosa API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 0.1.0 + * Generated by: https://github.com/openapitools/openapi-generator.git + */ + + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.IO; +using System.Runtime.Serialization; +using System.Text; +using System.Text.RegularExpressions; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using Newtonsoft.Json.Linq; +using OpenAPIDateConverter = Org.OpenAPITools.Client.OpenAPIDateConverter; + +namespace Org.OpenAPITools.Model +{ + /// + /// PatchUser + /// + [DataContract(Name = "PatchUser")] + public partial class PatchUser : IEquatable + { + /// + /// Initializes a new instance of the class. + /// + /// url. + /// displayname. + /// description. + public PatchUser(string url = default(string), string displayname = default(string), string description = default(string)) + { + this.Url = url; + this.Displayname = displayname; + this.Description = description; + } + + /// + /// Gets or Sets Url + /// + [DataMember(Name = "url", EmitDefaultValue = false)] + public string Url { get; set; } + + /// + /// Gets or Sets Displayname + /// + [DataMember(Name = "displayname", EmitDefaultValue = false)] + public string Displayname { get; set; } + + /// + /// Gets or Sets Description + /// + [DataMember(Name = "description", EmitDefaultValue = false)] + public string Description { get; set; } + + /// + /// Returns the string presentation of the object + /// + /// String presentation of the object + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + sb.Append("class PatchUser {\n"); + sb.Append(" Url: ").Append(Url).Append("\n"); + sb.Append(" Displayname: ").Append(Displayname).Append("\n"); + sb.Append(" Description: ").Append(Description).Append("\n"); + sb.Append("}\n"); + return sb.ToString(); + } + + /// + /// Returns the JSON string presentation of the object + /// + /// JSON string presentation of the object + public virtual string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented); + } + + /// + /// Returns true if objects are equal + /// + /// Object to be compared + /// Boolean + public override bool Equals(object input) + { + return this.Equals(input as PatchUser); + } + + /// + /// Returns true if PatchUser instances are equal + /// + /// Instance of PatchUser to be compared + /// Boolean + public bool Equals(PatchUser input) + { + if (input == null) + { + return false; + } + return + ( + this.Url == input.Url || + (this.Url != null && + this.Url.Equals(input.Url)) + ) && + ( + this.Displayname == input.Displayname || + (this.Displayname != null && + this.Displayname.Equals(input.Displayname)) + ) && + ( + this.Description == input.Description || + (this.Description != null && + this.Description.Equals(input.Description)) + ); + } + + /// + /// Gets the hash code + /// + /// Hash code + public override int GetHashCode() + { + unchecked // Overflow is fine, just wrap + { + int hashCode = 41; + if (this.Url != null) + { + hashCode = (hashCode * 59) + this.Url.GetHashCode(); + } + if (this.Displayname != null) + { + hashCode = (hashCode * 59) + this.Displayname.GetHashCode(); + } + if (this.Description != null) + { + hashCode = (hashCode * 59) + this.Description.GetHashCode(); + } + return hashCode; + } + } + + } + +} diff --git a/Assets/ThirdParty/Org.OpenAPITools/Model/PatchUser.cs.meta b/Assets/ThirdParty/Org.OpenAPITools/Model/PatchUser.cs.meta new file mode 100644 index 0000000000..6bdab916fc --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Model/PatchUser.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cb12ca9466d7b40839243f76e5c9d75a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThirdParty/Org.OpenAPITools/Model/PolyAsset.cs b/Assets/ThirdParty/Org.OpenAPITools/Model/PolyAsset.cs new file mode 100644 index 0000000000..9c46ad21c2 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Model/PolyAsset.cs @@ -0,0 +1,389 @@ +/* + * Icosa API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 0.1.0 + * Generated by: https://github.com/openapitools/openapi-generator.git + */ + + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.IO; +using System.Runtime.Serialization; +using System.Text; +using System.Text.RegularExpressions; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using Newtonsoft.Json.Linq; +using OpenAPIDateConverter = Org.OpenAPITools.Client.OpenAPIDateConverter; + +namespace Org.OpenAPITools.Model +{ + /// + /// PolyAsset + /// + [DataContract(Name = "PolyAsset")] + public partial class PolyAsset : IEquatable + { + /// + /// Initializes a new instance of the class. + /// + [JsonConstructorAttribute] + protected PolyAsset() { } + /// + /// Initializes a new instance of the class. + /// + /// name (required). + /// displayName (required). + /// authorName (required). + /// description. + /// createTime (required). + /// updateTime (required). + /// formats (required). + /// thumbnail. + /// licence. + /// visibility (required). + /// isCurated. + /// presentationParams. + /// metadata. + /// remixInfo. + public PolyAsset(string name = default(string), string displayName = default(string), string authorName = default(string), string description = default(string), string createTime = default(string), string updateTime = default(string), List formats = default(List), PolyResource thumbnail = default(PolyResource), string licence = default(string), string visibility = default(string), bool isCurated = default(bool), PolyPresentationParams presentationParams = default(PolyPresentationParams), string metadata = default(string), PolyRemixInfo remixInfo = default(PolyRemixInfo)) + { + // to ensure "name" is required (not null) + if (name == null) + { + throw new ArgumentNullException("name is a required property for PolyAsset and cannot be null"); + } + this.Name = name; + // to ensure "displayName" is required (not null) + if (displayName == null) + { + throw new ArgumentNullException("displayName is a required property for PolyAsset and cannot be null"); + } + this.DisplayName = displayName; + // to ensure "authorName" is required (not null) + if (authorName == null) + { + throw new ArgumentNullException("authorName is a required property for PolyAsset and cannot be null"); + } + this.AuthorName = authorName; + // to ensure "createTime" is required (not null) + if (createTime == null) + { + throw new ArgumentNullException("createTime is a required property for PolyAsset and cannot be null"); + } + this.CreateTime = createTime; + // to ensure "updateTime" is required (not null) + if (updateTime == null) + { + throw new ArgumentNullException("updateTime is a required property for PolyAsset and cannot be null"); + } + this.UpdateTime = updateTime; + // to ensure "formats" is required (not null) + if (formats == null) + { + throw new ArgumentNullException("formats is a required property for PolyAsset and cannot be null"); + } + this.Formats = formats; + // to ensure "visibility" is required (not null) + if (visibility == null) + { + throw new ArgumentNullException("visibility is a required property for PolyAsset and cannot be null"); + } + this.Visibility = visibility; + this.Description = description; + this.Thumbnail = thumbnail; + this.Licence = licence; + this.IsCurated = isCurated; + this.PresentationParams = presentationParams; + this.Metadata = metadata; + this.RemixInfo = remixInfo; + } + + /// + /// Gets or Sets Name + /// + [DataMember(Name = "name", IsRequired = true, EmitDefaultValue = true)] + public string Name { get; set; } + + /// + /// Gets or Sets DisplayName + /// + [DataMember(Name = "displayName", IsRequired = true, EmitDefaultValue = true)] + public string DisplayName { get; set; } + + /// + /// Gets or Sets AuthorName + /// + [DataMember(Name = "authorName", IsRequired = true, EmitDefaultValue = true)] + public string AuthorName { get; set; } + + /// + /// Gets or Sets Description + /// + [DataMember(Name = "description", EmitDefaultValue = false)] + public string Description { get; set; } + + /// + /// Gets or Sets CreateTime + /// + [DataMember(Name = "createTime", IsRequired = true, EmitDefaultValue = true)] + public string CreateTime { get; set; } + + /// + /// Gets or Sets UpdateTime + /// + [DataMember(Name = "updateTime", IsRequired = true, EmitDefaultValue = true)] + public string UpdateTime { get; set; } + + /// + /// Gets or Sets Formats + /// + [DataMember(Name = "formats", IsRequired = true, EmitDefaultValue = true)] + public List Formats { get; set; } + + /// + /// Gets or Sets Thumbnail + /// + [DataMember(Name = "thumbnail", EmitDefaultValue = false)] + public PolyResource Thumbnail { get; set; } + + /// + /// Gets or Sets Licence + /// + [DataMember(Name = "licence", EmitDefaultValue = false)] + public string Licence { get; set; } + + /// + /// Gets or Sets Visibility + /// + [DataMember(Name = "visibility", IsRequired = true, EmitDefaultValue = true)] + public string Visibility { get; set; } + + /// + /// Gets or Sets IsCurated + /// + [DataMember(Name = "isCurated", EmitDefaultValue = true)] + public bool IsCurated { get; set; } + + /// + /// Gets or Sets PresentationParams + /// + [DataMember(Name = "presentationParams", EmitDefaultValue = false)] + public PolyPresentationParams PresentationParams { get; set; } + + /// + /// Gets or Sets Metadata + /// + [DataMember(Name = "metadata", EmitDefaultValue = false)] + public string Metadata { get; set; } + + /// + /// Gets or Sets RemixInfo + /// + [DataMember(Name = "remixInfo", EmitDefaultValue = false)] + public PolyRemixInfo RemixInfo { get; set; } + + /// + /// Returns the string presentation of the object + /// + /// String presentation of the object + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + sb.Append("class PolyAsset {\n"); + sb.Append(" Name: ").Append(Name).Append("\n"); + sb.Append(" DisplayName: ").Append(DisplayName).Append("\n"); + sb.Append(" AuthorName: ").Append(AuthorName).Append("\n"); + sb.Append(" Description: ").Append(Description).Append("\n"); + sb.Append(" CreateTime: ").Append(CreateTime).Append("\n"); + sb.Append(" UpdateTime: ").Append(UpdateTime).Append("\n"); + sb.Append(" Formats: ").Append(Formats).Append("\n"); + sb.Append(" Thumbnail: ").Append(Thumbnail).Append("\n"); + sb.Append(" Licence: ").Append(Licence).Append("\n"); + sb.Append(" Visibility: ").Append(Visibility).Append("\n"); + sb.Append(" IsCurated: ").Append(IsCurated).Append("\n"); + sb.Append(" PresentationParams: ").Append(PresentationParams).Append("\n"); + sb.Append(" Metadata: ").Append(Metadata).Append("\n"); + sb.Append(" RemixInfo: ").Append(RemixInfo).Append("\n"); + sb.Append("}\n"); + return sb.ToString(); + } + + /// + /// Returns the JSON string presentation of the object + /// + /// JSON string presentation of the object + public virtual string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented); + } + + /// + /// Returns true if objects are equal + /// + /// Object to be compared + /// Boolean + public override bool Equals(object input) + { + return this.Equals(input as PolyAsset); + } + + /// + /// Returns true if PolyAsset instances are equal + /// + /// Instance of PolyAsset to be compared + /// Boolean + public bool Equals(PolyAsset input) + { + if (input == null) + { + return false; + } + return + ( + this.Name == input.Name || + (this.Name != null && + this.Name.Equals(input.Name)) + ) && + ( + this.DisplayName == input.DisplayName || + (this.DisplayName != null && + this.DisplayName.Equals(input.DisplayName)) + ) && + ( + this.AuthorName == input.AuthorName || + (this.AuthorName != null && + this.AuthorName.Equals(input.AuthorName)) + ) && + ( + this.Description == input.Description || + (this.Description != null && + this.Description.Equals(input.Description)) + ) && + ( + this.CreateTime == input.CreateTime || + (this.CreateTime != null && + this.CreateTime.Equals(input.CreateTime)) + ) && + ( + this.UpdateTime == input.UpdateTime || + (this.UpdateTime != null && + this.UpdateTime.Equals(input.UpdateTime)) + ) && + ( + this.Formats == input.Formats || + this.Formats != null && + input.Formats != null && + this.Formats.SequenceEqual(input.Formats) + ) && + ( + this.Thumbnail == input.Thumbnail || + (this.Thumbnail != null && + this.Thumbnail.Equals(input.Thumbnail)) + ) && + ( + this.Licence == input.Licence || + (this.Licence != null && + this.Licence.Equals(input.Licence)) + ) && + ( + this.Visibility == input.Visibility || + (this.Visibility != null && + this.Visibility.Equals(input.Visibility)) + ) && + ( + this.IsCurated == input.IsCurated || + this.IsCurated.Equals(input.IsCurated) + ) && + ( + this.PresentationParams == input.PresentationParams || + (this.PresentationParams != null && + this.PresentationParams.Equals(input.PresentationParams)) + ) && + ( + this.Metadata == input.Metadata || + (this.Metadata != null && + this.Metadata.Equals(input.Metadata)) + ) && + ( + this.RemixInfo == input.RemixInfo || + (this.RemixInfo != null && + this.RemixInfo.Equals(input.RemixInfo)) + ); + } + + /// + /// Gets the hash code + /// + /// Hash code + public override int GetHashCode() + { + unchecked // Overflow is fine, just wrap + { + int hashCode = 41; + if (this.Name != null) + { + hashCode = (hashCode * 59) + this.Name.GetHashCode(); + } + if (this.DisplayName != null) + { + hashCode = (hashCode * 59) + this.DisplayName.GetHashCode(); + } + if (this.AuthorName != null) + { + hashCode = (hashCode * 59) + this.AuthorName.GetHashCode(); + } + if (this.Description != null) + { + hashCode = (hashCode * 59) + this.Description.GetHashCode(); + } + if (this.CreateTime != null) + { + hashCode = (hashCode * 59) + this.CreateTime.GetHashCode(); + } + if (this.UpdateTime != null) + { + hashCode = (hashCode * 59) + this.UpdateTime.GetHashCode(); + } + if (this.Formats != null) + { + hashCode = (hashCode * 59) + this.Formats.GetHashCode(); + } + if (this.Thumbnail != null) + { + hashCode = (hashCode * 59) + this.Thumbnail.GetHashCode(); + } + if (this.Licence != null) + { + hashCode = (hashCode * 59) + this.Licence.GetHashCode(); + } + if (this.Visibility != null) + { + hashCode = (hashCode * 59) + this.Visibility.GetHashCode(); + } + hashCode = (hashCode * 59) + this.IsCurated.GetHashCode(); + if (this.PresentationParams != null) + { + hashCode = (hashCode * 59) + this.PresentationParams.GetHashCode(); + } + if (this.Metadata != null) + { + hashCode = (hashCode * 59) + this.Metadata.GetHashCode(); + } + if (this.RemixInfo != null) + { + hashCode = (hashCode * 59) + this.RemixInfo.GetHashCode(); + } + return hashCode; + } + } + + } + +} diff --git a/Assets/ThirdParty/Org.OpenAPITools/Model/PolyAsset.cs.meta b/Assets/ThirdParty/Org.OpenAPITools/Model/PolyAsset.cs.meta new file mode 100644 index 0000000000..8cdb879940 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Model/PolyAsset.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cba052ff7b6d24b26b230f54695bc70b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThirdParty/Org.OpenAPITools/Model/PolyFormat.cs b/Assets/ThirdParty/Org.OpenAPITools/Model/PolyFormat.cs new file mode 100644 index 0000000000..aac6154011 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Model/PolyFormat.cs @@ -0,0 +1,193 @@ +/* + * Icosa API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 0.1.0 + * Generated by: https://github.com/openapitools/openapi-generator.git + */ + + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.IO; +using System.Runtime.Serialization; +using System.Text; +using System.Text.RegularExpressions; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using Newtonsoft.Json.Linq; +using OpenAPIDateConverter = Org.OpenAPITools.Client.OpenAPIDateConverter; + +namespace Org.OpenAPITools.Model +{ + /// + /// PolyFormat + /// + [DataContract(Name = "PolyFormat")] + public partial class PolyFormat : IEquatable + { + /// + /// Initializes a new instance of the class. + /// + [JsonConstructorAttribute] + protected PolyFormat() { } + /// + /// Initializes a new instance of the class. + /// + /// root (required). + /// resources. + /// formatComplexity (required). + /// formatType (required). + public PolyFormat(PolyResource root = default(PolyResource), List resources = default(List), PolyFormatComplexity formatComplexity = default(PolyFormatComplexity), string formatType = default(string)) + { + // to ensure "root" is required (not null) + if (root == null) + { + throw new ArgumentNullException("root is a required property for PolyFormat and cannot be null"); + } + this.Root = root; + // to ensure "formatComplexity" is required (not null) + if (formatComplexity == null) + { + throw new ArgumentNullException("formatComplexity is a required property for PolyFormat and cannot be null"); + } + this.FormatComplexity = formatComplexity; + // to ensure "formatType" is required (not null) + if (formatType == null) + { + throw new ArgumentNullException("formatType is a required property for PolyFormat and cannot be null"); + } + this.FormatType = formatType; + this.Resources = resources; + } + + /// + /// Gets or Sets Root + /// + [DataMember(Name = "root", IsRequired = true, EmitDefaultValue = true)] + public PolyResource Root { get; set; } + + /// + /// Gets or Sets Resources + /// + [DataMember(Name = "resources", EmitDefaultValue = false)] + public List Resources { get; set; } + + /// + /// Gets or Sets FormatComplexity + /// + [DataMember(Name = "formatComplexity", IsRequired = true, EmitDefaultValue = true)] + public PolyFormatComplexity FormatComplexity { get; set; } + + /// + /// Gets or Sets FormatType + /// + [DataMember(Name = "formatType", IsRequired = true, EmitDefaultValue = true)] + public string FormatType { get; set; } + + /// + /// Returns the string presentation of the object + /// + /// String presentation of the object + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + sb.Append("class PolyFormat {\n"); + sb.Append(" Root: ").Append(Root).Append("\n"); + sb.Append(" Resources: ").Append(Resources).Append("\n"); + sb.Append(" FormatComplexity: ").Append(FormatComplexity).Append("\n"); + sb.Append(" FormatType: ").Append(FormatType).Append("\n"); + sb.Append("}\n"); + return sb.ToString(); + } + + /// + /// Returns the JSON string presentation of the object + /// + /// JSON string presentation of the object + public virtual string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented); + } + + /// + /// Returns true if objects are equal + /// + /// Object to be compared + /// Boolean + public override bool Equals(object input) + { + return this.Equals(input as PolyFormat); + } + + /// + /// Returns true if PolyFormat instances are equal + /// + /// Instance of PolyFormat to be compared + /// Boolean + public bool Equals(PolyFormat input) + { + if (input == null) + { + return false; + } + return + ( + this.Root == input.Root || + (this.Root != null && + this.Root.Equals(input.Root)) + ) && + ( + this.Resources == input.Resources || + this.Resources != null && + input.Resources != null && + this.Resources.SequenceEqual(input.Resources) + ) && + ( + this.FormatComplexity == input.FormatComplexity || + (this.FormatComplexity != null && + this.FormatComplexity.Equals(input.FormatComplexity)) + ) && + ( + this.FormatType == input.FormatType || + (this.FormatType != null && + this.FormatType.Equals(input.FormatType)) + ); + } + + /// + /// Gets the hash code + /// + /// Hash code + public override int GetHashCode() + { + unchecked // Overflow is fine, just wrap + { + int hashCode = 41; + if (this.Root != null) + { + hashCode = (hashCode * 59) + this.Root.GetHashCode(); + } + if (this.Resources != null) + { + hashCode = (hashCode * 59) + this.Resources.GetHashCode(); + } + if (this.FormatComplexity != null) + { + hashCode = (hashCode * 59) + this.FormatComplexity.GetHashCode(); + } + if (this.FormatType != null) + { + hashCode = (hashCode * 59) + this.FormatType.GetHashCode(); + } + return hashCode; + } + } + + } + +} diff --git a/Assets/ThirdParty/Org.OpenAPITools/Model/PolyFormat.cs.meta b/Assets/ThirdParty/Org.OpenAPITools/Model/PolyFormat.cs.meta new file mode 100644 index 0000000000..1cfd4cf989 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Model/PolyFormat.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8d331fb7a3d374da9a07b7582b759b28 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThirdParty/Org.OpenAPITools/Model/PolyFormatComplexity.cs b/Assets/ThirdParty/Org.OpenAPITools/Model/PolyFormatComplexity.cs new file mode 100644 index 0000000000..9e193ee06f --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Model/PolyFormatComplexity.cs @@ -0,0 +1,132 @@ +/* + * Icosa API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 0.1.0 + * Generated by: https://github.com/openapitools/openapi-generator.git + */ + + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.IO; +using System.Runtime.Serialization; +using System.Text; +using System.Text.RegularExpressions; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using Newtonsoft.Json.Linq; +using OpenAPIDateConverter = Org.OpenAPITools.Client.OpenAPIDateConverter; + +namespace Org.OpenAPITools.Model +{ + /// + /// PolyFormatComplexity + /// + [DataContract(Name = "PolyFormatComplexity")] + public partial class PolyFormatComplexity : IEquatable + { + /// + /// Initializes a new instance of the class. + /// + /// triangleCount. + /// lodHint. + public PolyFormatComplexity(string triangleCount = default(string), int lodHint = default(int)) + { + this.TriangleCount = triangleCount; + this.LodHint = lodHint; + } + + /// + /// Gets or Sets TriangleCount + /// + [DataMember(Name = "triangleCount", EmitDefaultValue = false)] + public string TriangleCount { get; set; } + + /// + /// Gets or Sets LodHint + /// + [DataMember(Name = "lodHint", EmitDefaultValue = false)] + public int LodHint { get; set; } + + /// + /// Returns the string presentation of the object + /// + /// String presentation of the object + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + sb.Append("class PolyFormatComplexity {\n"); + sb.Append(" TriangleCount: ").Append(TriangleCount).Append("\n"); + sb.Append(" LodHint: ").Append(LodHint).Append("\n"); + sb.Append("}\n"); + return sb.ToString(); + } + + /// + /// Returns the JSON string presentation of the object + /// + /// JSON string presentation of the object + public virtual string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented); + } + + /// + /// Returns true if objects are equal + /// + /// Object to be compared + /// Boolean + public override bool Equals(object input) + { + return this.Equals(input as PolyFormatComplexity); + } + + /// + /// Returns true if PolyFormatComplexity instances are equal + /// + /// Instance of PolyFormatComplexity to be compared + /// Boolean + public bool Equals(PolyFormatComplexity input) + { + if (input == null) + { + return false; + } + return + ( + this.TriangleCount == input.TriangleCount || + (this.TriangleCount != null && + this.TriangleCount.Equals(input.TriangleCount)) + ) && + ( + this.LodHint == input.LodHint || + this.LodHint.Equals(input.LodHint) + ); + } + + /// + /// Gets the hash code + /// + /// Hash code + public override int GetHashCode() + { + unchecked // Overflow is fine, just wrap + { + int hashCode = 41; + if (this.TriangleCount != null) + { + hashCode = (hashCode * 59) + this.TriangleCount.GetHashCode(); + } + hashCode = (hashCode * 59) + this.LodHint.GetHashCode(); + return hashCode; + } + } + + } + +} diff --git a/Assets/ThirdParty/Org.OpenAPITools/Model/PolyFormatComplexity.cs.meta b/Assets/ThirdParty/Org.OpenAPITools/Model/PolyFormatComplexity.cs.meta new file mode 100644 index 0000000000..3c2f80d3c7 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Model/PolyFormatComplexity.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8fb711e277e9f492bb50291860a2304f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThirdParty/Org.OpenAPITools/Model/PolyList.cs b/Assets/ThirdParty/Org.OpenAPITools/Model/PolyList.cs new file mode 100644 index 0000000000..2c795e51aa --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Model/PolyList.cs @@ -0,0 +1,166 @@ +/* + * Icosa API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 0.1.0 + * Generated by: https://github.com/openapitools/openapi-generator.git + */ + + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.IO; +using System.Runtime.Serialization; +using System.Text; +using System.Text.RegularExpressions; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using Newtonsoft.Json.Linq; +using OpenAPIDateConverter = Org.OpenAPITools.Client.OpenAPIDateConverter; + +namespace Org.OpenAPITools.Model +{ + /// + /// PolyList + /// + [DataContract(Name = "PolyList")] + public partial class PolyList : IEquatable + { + /// + /// Initializes a new instance of the class. + /// + [JsonConstructorAttribute] + protected PolyList() { } + /// + /// Initializes a new instance of the class. + /// + /// assets (required). + /// nextPageToken (required). + /// totalSize (required). + public PolyList(List assets = default(List), string nextPageToken = default(string), int totalSize = default(int)) + { + // to ensure "assets" is required (not null) + if (assets == null) + { + throw new ArgumentNullException("assets is a required property for PolyList and cannot be null"); + } + this.Assets = assets; + // to ensure "nextPageToken" is required (not null) + if (nextPageToken == null) + { + throw new ArgumentNullException("nextPageToken is a required property for PolyList and cannot be null"); + } + this.NextPageToken = nextPageToken; + this.TotalSize = totalSize; + } + + /// + /// Gets or Sets Assets + /// + [DataMember(Name = "assets", IsRequired = true, EmitDefaultValue = true)] + public List Assets { get; set; } + + /// + /// Gets or Sets NextPageToken + /// + [DataMember(Name = "nextPageToken", IsRequired = true, EmitDefaultValue = true)] + public string NextPageToken { get; set; } + + /// + /// Gets or Sets TotalSize + /// + [DataMember(Name = "totalSize", IsRequired = true, EmitDefaultValue = true)] + public int TotalSize { get; set; } + + /// + /// Returns the string presentation of the object + /// + /// String presentation of the object + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + sb.Append("class PolyList {\n"); + sb.Append(" Assets: ").Append(Assets).Append("\n"); + sb.Append(" NextPageToken: ").Append(NextPageToken).Append("\n"); + sb.Append(" TotalSize: ").Append(TotalSize).Append("\n"); + sb.Append("}\n"); + return sb.ToString(); + } + + /// + /// Returns the JSON string presentation of the object + /// + /// JSON string presentation of the object + public virtual string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented); + } + + /// + /// Returns true if objects are equal + /// + /// Object to be compared + /// Boolean + public override bool Equals(object input) + { + return this.Equals(input as PolyList); + } + + /// + /// Returns true if PolyList instances are equal + /// + /// Instance of PolyList to be compared + /// Boolean + public bool Equals(PolyList input) + { + if (input == null) + { + return false; + } + return + ( + this.Assets == input.Assets || + this.Assets != null && + input.Assets != null && + this.Assets.SequenceEqual(input.Assets) + ) && + ( + this.NextPageToken == input.NextPageToken || + (this.NextPageToken != null && + this.NextPageToken.Equals(input.NextPageToken)) + ) && + ( + this.TotalSize == input.TotalSize || + this.TotalSize.Equals(input.TotalSize) + ); + } + + /// + /// Gets the hash code + /// + /// Hash code + public override int GetHashCode() + { + unchecked // Overflow is fine, just wrap + { + int hashCode = 41; + if (this.Assets != null) + { + hashCode = (hashCode * 59) + this.Assets.GetHashCode(); + } + if (this.NextPageToken != null) + { + hashCode = (hashCode * 59) + this.NextPageToken.GetHashCode(); + } + hashCode = (hashCode * 59) + this.TotalSize.GetHashCode(); + return hashCode; + } + } + + } + +} diff --git a/Assets/ThirdParty/Org.OpenAPITools/Model/PolyList.cs.meta b/Assets/ThirdParty/Org.OpenAPITools/Model/PolyList.cs.meta new file mode 100644 index 0000000000..f16e09e64d --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Model/PolyList.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 494fa7b70cee041a7aaf90b1af006624 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThirdParty/Org.OpenAPITools/Model/PolyPresentationParams.cs b/Assets/ThirdParty/Org.OpenAPITools/Model/PolyPresentationParams.cs new file mode 100644 index 0000000000..670168e72f --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Model/PolyPresentationParams.cs @@ -0,0 +1,154 @@ +/* + * Icosa API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 0.1.0 + * Generated by: https://github.com/openapitools/openapi-generator.git + */ + + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.IO; +using System.Runtime.Serialization; +using System.Text; +using System.Text.RegularExpressions; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using Newtonsoft.Json.Linq; +using OpenAPIDateConverter = Org.OpenAPITools.Client.OpenAPIDateConverter; + +namespace Org.OpenAPITools.Model +{ + /// + /// PolyPresentationParams + /// + [DataContract(Name = "PolyPresentationParams")] + public partial class PolyPresentationParams : IEquatable + { + /// + /// Initializes a new instance of the class. + /// + /// orientingRotation. + /// colorSpace. + /// backgroundColor. + public PolyPresentationParams(PolyQuaternion orientingRotation = default(PolyQuaternion), string colorSpace = default(string), string backgroundColor = default(string)) + { + this.OrientingRotation = orientingRotation; + this.ColorSpace = colorSpace; + this.BackgroundColor = backgroundColor; + } + + /// + /// Gets or Sets OrientingRotation + /// + [DataMember(Name = "orientingRotation", EmitDefaultValue = false)] + public PolyQuaternion OrientingRotation { get; set; } + + /// + /// Gets or Sets ColorSpace + /// + [DataMember(Name = "colorSpace", EmitDefaultValue = false)] + public string ColorSpace { get; set; } + + /// + /// Gets or Sets BackgroundColor + /// + [DataMember(Name = "backgroundColor", EmitDefaultValue = false)] + public string BackgroundColor { get; set; } + + /// + /// Returns the string presentation of the object + /// + /// String presentation of the object + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + sb.Append("class PolyPresentationParams {\n"); + sb.Append(" OrientingRotation: ").Append(OrientingRotation).Append("\n"); + sb.Append(" ColorSpace: ").Append(ColorSpace).Append("\n"); + sb.Append(" BackgroundColor: ").Append(BackgroundColor).Append("\n"); + sb.Append("}\n"); + return sb.ToString(); + } + + /// + /// Returns the JSON string presentation of the object + /// + /// JSON string presentation of the object + public virtual string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented); + } + + /// + /// Returns true if objects are equal + /// + /// Object to be compared + /// Boolean + public override bool Equals(object input) + { + return this.Equals(input as PolyPresentationParams); + } + + /// + /// Returns true if PolyPresentationParams instances are equal + /// + /// Instance of PolyPresentationParams to be compared + /// Boolean + public bool Equals(PolyPresentationParams input) + { + if (input == null) + { + return false; + } + return + ( + this.OrientingRotation == input.OrientingRotation || + (this.OrientingRotation != null && + this.OrientingRotation.Equals(input.OrientingRotation)) + ) && + ( + this.ColorSpace == input.ColorSpace || + (this.ColorSpace != null && + this.ColorSpace.Equals(input.ColorSpace)) + ) && + ( + this.BackgroundColor == input.BackgroundColor || + (this.BackgroundColor != null && + this.BackgroundColor.Equals(input.BackgroundColor)) + ); + } + + /// + /// Gets the hash code + /// + /// Hash code + public override int GetHashCode() + { + unchecked // Overflow is fine, just wrap + { + int hashCode = 41; + if (this.OrientingRotation != null) + { + hashCode = (hashCode * 59) + this.OrientingRotation.GetHashCode(); + } + if (this.ColorSpace != null) + { + hashCode = (hashCode * 59) + this.ColorSpace.GetHashCode(); + } + if (this.BackgroundColor != null) + { + hashCode = (hashCode * 59) + this.BackgroundColor.GetHashCode(); + } + return hashCode; + } + } + + } + +} diff --git a/Assets/ThirdParty/Org.OpenAPITools/Model/PolyPresentationParams.cs.meta b/Assets/ThirdParty/Org.OpenAPITools/Model/PolyPresentationParams.cs.meta new file mode 100644 index 0000000000..047ea8a440 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Model/PolyPresentationParams.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 85d7678a5f346475996c5d4ea9b4865a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThirdParty/Org.OpenAPITools/Model/PolyQuaternion.cs b/Assets/ThirdParty/Org.OpenAPITools/Model/PolyQuaternion.cs new file mode 100644 index 0000000000..9cd2712d36 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Model/PolyQuaternion.cs @@ -0,0 +1,156 @@ +/* + * Icosa API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 0.1.0 + * Generated by: https://github.com/openapitools/openapi-generator.git + */ + + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.IO; +using System.Runtime.Serialization; +using System.Text; +using System.Text.RegularExpressions; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using Newtonsoft.Json.Linq; +using OpenAPIDateConverter = Org.OpenAPITools.Client.OpenAPIDateConverter; + +namespace Org.OpenAPITools.Model +{ + /// + /// PolyQuaternion + /// + [DataContract(Name = "PolyQuaternion")] + public partial class PolyQuaternion : IEquatable + { + /// + /// Initializes a new instance of the class. + /// + /// x. + /// y. + /// z. + /// w. + public PolyQuaternion(decimal x = default(decimal), decimal y = default(decimal), decimal z = default(decimal), decimal w = default(decimal)) + { + this.X = x; + this.Y = y; + this.Z = z; + this.W = w; + } + + /// + /// Gets or Sets X + /// + [DataMember(Name = "x", EmitDefaultValue = false)] + public decimal X { get; set; } + + /// + /// Gets or Sets Y + /// + [DataMember(Name = "y", EmitDefaultValue = false)] + public decimal Y { get; set; } + + /// + /// Gets or Sets Z + /// + [DataMember(Name = "z", EmitDefaultValue = false)] + public decimal Z { get; set; } + + /// + /// Gets or Sets W + /// + [DataMember(Name = "w", EmitDefaultValue = false)] + public decimal W { get; set; } + + /// + /// Returns the string presentation of the object + /// + /// String presentation of the object + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + sb.Append("class PolyQuaternion {\n"); + sb.Append(" X: ").Append(X).Append("\n"); + sb.Append(" Y: ").Append(Y).Append("\n"); + sb.Append(" Z: ").Append(Z).Append("\n"); + sb.Append(" W: ").Append(W).Append("\n"); + sb.Append("}\n"); + return sb.ToString(); + } + + /// + /// Returns the JSON string presentation of the object + /// + /// JSON string presentation of the object + public virtual string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented); + } + + /// + /// Returns true if objects are equal + /// + /// Object to be compared + /// Boolean + public override bool Equals(object input) + { + return this.Equals(input as PolyQuaternion); + } + + /// + /// Returns true if PolyQuaternion instances are equal + /// + /// Instance of PolyQuaternion to be compared + /// Boolean + public bool Equals(PolyQuaternion input) + { + if (input == null) + { + return false; + } + return + ( + this.X == input.X || + this.X.Equals(input.X) + ) && + ( + this.Y == input.Y || + this.Y.Equals(input.Y) + ) && + ( + this.Z == input.Z || + this.Z.Equals(input.Z) + ) && + ( + this.W == input.W || + this.W.Equals(input.W) + ); + } + + /// + /// Gets the hash code + /// + /// Hash code + public override int GetHashCode() + { + unchecked // Overflow is fine, just wrap + { + int hashCode = 41; + hashCode = (hashCode * 59) + this.X.GetHashCode(); + hashCode = (hashCode * 59) + this.Y.GetHashCode(); + hashCode = (hashCode * 59) + this.Z.GetHashCode(); + hashCode = (hashCode * 59) + this.W.GetHashCode(); + return hashCode; + } + } + + } + +} diff --git a/Assets/ThirdParty/Org.OpenAPITools/Model/PolyQuaternion.cs.meta b/Assets/ThirdParty/Org.OpenAPITools/Model/PolyQuaternion.cs.meta new file mode 100644 index 0000000000..38d102450c --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Model/PolyQuaternion.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 513cabfeb87854824853864d5552e5f3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThirdParty/Org.OpenAPITools/Model/PolyRemixInfo.cs b/Assets/ThirdParty/Org.OpenAPITools/Model/PolyRemixInfo.cs new file mode 100644 index 0000000000..152eafc33b --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Model/PolyRemixInfo.cs @@ -0,0 +1,129 @@ +/* + * Icosa API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 0.1.0 + * Generated by: https://github.com/openapitools/openapi-generator.git + */ + + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.IO; +using System.Runtime.Serialization; +using System.Text; +using System.Text.RegularExpressions; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using Newtonsoft.Json.Linq; +using OpenAPIDateConverter = Org.OpenAPITools.Client.OpenAPIDateConverter; + +namespace Org.OpenAPITools.Model +{ + /// + /// PolyRemixInfo + /// + [DataContract(Name = "PolyRemixInfo")] + public partial class PolyRemixInfo : IEquatable + { + /// + /// Initializes a new instance of the class. + /// + [JsonConstructorAttribute] + protected PolyRemixInfo() { } + /// + /// Initializes a new instance of the class. + /// + /// sourceAsset (required). + public PolyRemixInfo(List sourceAsset = default(List)) + { + // to ensure "sourceAsset" is required (not null) + if (sourceAsset == null) + { + throw new ArgumentNullException("sourceAsset is a required property for PolyRemixInfo and cannot be null"); + } + this.SourceAsset = sourceAsset; + } + + /// + /// Gets or Sets SourceAsset + /// + [DataMember(Name = "sourceAsset", IsRequired = true, EmitDefaultValue = true)] + public List SourceAsset { get; set; } + + /// + /// Returns the string presentation of the object + /// + /// String presentation of the object + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + sb.Append("class PolyRemixInfo {\n"); + sb.Append(" SourceAsset: ").Append(SourceAsset).Append("\n"); + sb.Append("}\n"); + return sb.ToString(); + } + + /// + /// Returns the JSON string presentation of the object + /// + /// JSON string presentation of the object + public virtual string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented); + } + + /// + /// Returns true if objects are equal + /// + /// Object to be compared + /// Boolean + public override bool Equals(object input) + { + return this.Equals(input as PolyRemixInfo); + } + + /// + /// Returns true if PolyRemixInfo instances are equal + /// + /// Instance of PolyRemixInfo to be compared + /// Boolean + public bool Equals(PolyRemixInfo input) + { + if (input == null) + { + return false; + } + return + ( + this.SourceAsset == input.SourceAsset || + this.SourceAsset != null && + input.SourceAsset != null && + this.SourceAsset.SequenceEqual(input.SourceAsset) + ); + } + + /// + /// Gets the hash code + /// + /// Hash code + public override int GetHashCode() + { + unchecked // Overflow is fine, just wrap + { + int hashCode = 41; + if (this.SourceAsset != null) + { + hashCode = (hashCode * 59) + this.SourceAsset.GetHashCode(); + } + return hashCode; + } + } + + } + +} diff --git a/Assets/ThirdParty/Org.OpenAPITools/Model/PolyRemixInfo.cs.meta b/Assets/ThirdParty/Org.OpenAPITools/Model/PolyRemixInfo.cs.meta new file mode 100644 index 0000000000..851048f618 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Model/PolyRemixInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 622877854add744b09304bde8fdccf57 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThirdParty/Org.OpenAPITools/Model/PolyResource.cs b/Assets/ThirdParty/Org.OpenAPITools/Model/PolyResource.cs new file mode 100644 index 0000000000..aef3e28cd6 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Model/PolyResource.cs @@ -0,0 +1,174 @@ +/* + * Icosa API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 0.1.0 + * Generated by: https://github.com/openapitools/openapi-generator.git + */ + + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.IO; +using System.Runtime.Serialization; +using System.Text; +using System.Text.RegularExpressions; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using Newtonsoft.Json.Linq; +using OpenAPIDateConverter = Org.OpenAPITools.Client.OpenAPIDateConverter; + +namespace Org.OpenAPITools.Model +{ + /// + /// PolyResource + /// + [DataContract(Name = "PolyResource")] + public partial class PolyResource : IEquatable + { + /// + /// Initializes a new instance of the class. + /// + [JsonConstructorAttribute] + protected PolyResource() { } + /// + /// Initializes a new instance of the class. + /// + /// relativePath (required). + /// url (required). + /// contentType (required). + public PolyResource(string relativePath = default(string), string url = default(string), string contentType = default(string)) + { + // to ensure "relativePath" is required (not null) + if (relativePath == null) + { + throw new ArgumentNullException("relativePath is a required property for PolyResource and cannot be null"); + } + this.RelativePath = relativePath; + // to ensure "url" is required (not null) + if (url == null) + { + throw new ArgumentNullException("url is a required property for PolyResource and cannot be null"); + } + this.Url = url; + // to ensure "contentType" is required (not null) + if (contentType == null) + { + throw new ArgumentNullException("contentType is a required property for PolyResource and cannot be null"); + } + this.ContentType = contentType; + } + + /// + /// Gets or Sets RelativePath + /// + [DataMember(Name = "relativePath", IsRequired = true, EmitDefaultValue = true)] + public string RelativePath { get; set; } + + /// + /// Gets or Sets Url + /// + [DataMember(Name = "url", IsRequired = true, EmitDefaultValue = true)] + public string Url { get; set; } + + /// + /// Gets or Sets ContentType + /// + [DataMember(Name = "contentType", IsRequired = true, EmitDefaultValue = true)] + public string ContentType { get; set; } + + /// + /// Returns the string presentation of the object + /// + /// String presentation of the object + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + sb.Append("class PolyResource {\n"); + sb.Append(" RelativePath: ").Append(RelativePath).Append("\n"); + sb.Append(" Url: ").Append(Url).Append("\n"); + sb.Append(" ContentType: ").Append(ContentType).Append("\n"); + sb.Append("}\n"); + return sb.ToString(); + } + + /// + /// Returns the JSON string presentation of the object + /// + /// JSON string presentation of the object + public virtual string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented); + } + + /// + /// Returns true if objects are equal + /// + /// Object to be compared + /// Boolean + public override bool Equals(object input) + { + return this.Equals(input as PolyResource); + } + + /// + /// Returns true if PolyResource instances are equal + /// + /// Instance of PolyResource to be compared + /// Boolean + public bool Equals(PolyResource input) + { + if (input == null) + { + return false; + } + return + ( + this.RelativePath == input.RelativePath || + (this.RelativePath != null && + this.RelativePath.Equals(input.RelativePath)) + ) && + ( + this.Url == input.Url || + (this.Url != null && + this.Url.Equals(input.Url)) + ) && + ( + this.ContentType == input.ContentType || + (this.ContentType != null && + this.ContentType.Equals(input.ContentType)) + ); + } + + /// + /// Gets the hash code + /// + /// Hash code + public override int GetHashCode() + { + unchecked // Overflow is fine, just wrap + { + int hashCode = 41; + if (this.RelativePath != null) + { + hashCode = (hashCode * 59) + this.RelativePath.GetHashCode(); + } + if (this.Url != null) + { + hashCode = (hashCode * 59) + this.Url.GetHashCode(); + } + if (this.ContentType != null) + { + hashCode = (hashCode * 59) + this.ContentType.GetHashCode(); + } + return hashCode; + } + } + + } + +} diff --git a/Assets/ThirdParty/Org.OpenAPITools/Model/PolyResource.cs.meta b/Assets/ThirdParty/Org.OpenAPITools/Model/PolyResource.cs.meta new file mode 100644 index 0000000000..93ad79dc56 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Model/PolyResource.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 99c97d18903a7424280769ad0ce3adac +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThirdParty/Org.OpenAPITools/Model/SubAssetFormat.cs b/Assets/ThirdParty/Org.OpenAPITools/Model/SubAssetFormat.cs new file mode 100644 index 0000000000..0bb069a7c6 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Model/SubAssetFormat.cs @@ -0,0 +1,174 @@ +/* + * Icosa API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 0.1.0 + * Generated by: https://github.com/openapitools/openapi-generator.git + */ + + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.IO; +using System.Runtime.Serialization; +using System.Text; +using System.Text.RegularExpressions; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using Newtonsoft.Json.Linq; +using OpenAPIDateConverter = Org.OpenAPITools.Client.OpenAPIDateConverter; + +namespace Org.OpenAPITools.Model +{ + /// + /// SubAssetFormat + /// + [DataContract(Name = "SubAssetFormat")] + public partial class SubAssetFormat : IEquatable + { + /// + /// Initializes a new instance of the class. + /// + [JsonConstructorAttribute] + protected SubAssetFormat() { } + /// + /// Initializes a new instance of the class. + /// + /// id (required). + /// url (required). + /// format (required). + public SubAssetFormat(string id = default(string), string url = default(string), string format = default(string)) + { + // to ensure "id" is required (not null) + if (id == null) + { + throw new ArgumentNullException("id is a required property for SubAssetFormat and cannot be null"); + } + this.Id = id; + // to ensure "url" is required (not null) + if (url == null) + { + throw new ArgumentNullException("url is a required property for SubAssetFormat and cannot be null"); + } + this.Url = url; + // to ensure "format" is required (not null) + if (format == null) + { + throw new ArgumentNullException("format is a required property for SubAssetFormat and cannot be null"); + } + this.Format = format; + } + + /// + /// Gets or Sets Id + /// + [DataMember(Name = "id", IsRequired = true, EmitDefaultValue = true)] + public string Id { get; set; } + + /// + /// Gets or Sets Url + /// + [DataMember(Name = "url", IsRequired = true, EmitDefaultValue = true)] + public string Url { get; set; } + + /// + /// Gets or Sets Format + /// + [DataMember(Name = "format", IsRequired = true, EmitDefaultValue = true)] + public string Format { get; set; } + + /// + /// Returns the string presentation of the object + /// + /// String presentation of the object + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + sb.Append("class SubAssetFormat {\n"); + sb.Append(" Id: ").Append(Id).Append("\n"); + sb.Append(" Url: ").Append(Url).Append("\n"); + sb.Append(" Format: ").Append(Format).Append("\n"); + sb.Append("}\n"); + return sb.ToString(); + } + + /// + /// Returns the JSON string presentation of the object + /// + /// JSON string presentation of the object + public virtual string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented); + } + + /// + /// Returns true if objects are equal + /// + /// Object to be compared + /// Boolean + public override bool Equals(object input) + { + return this.Equals(input as SubAssetFormat); + } + + /// + /// Returns true if SubAssetFormat instances are equal + /// + /// Instance of SubAssetFormat to be compared + /// Boolean + public bool Equals(SubAssetFormat input) + { + if (input == null) + { + return false; + } + return + ( + this.Id == input.Id || + (this.Id != null && + this.Id.Equals(input.Id)) + ) && + ( + this.Url == input.Url || + (this.Url != null && + this.Url.Equals(input.Url)) + ) && + ( + this.Format == input.Format || + (this.Format != null && + this.Format.Equals(input.Format)) + ); + } + + /// + /// Gets the hash code + /// + /// Hash code + public override int GetHashCode() + { + unchecked // Overflow is fine, just wrap + { + int hashCode = 41; + if (this.Id != null) + { + hashCode = (hashCode * 59) + this.Id.GetHashCode(); + } + if (this.Url != null) + { + hashCode = (hashCode * 59) + this.Url.GetHashCode(); + } + if (this.Format != null) + { + hashCode = (hashCode * 59) + this.Format.GetHashCode(); + } + return hashCode; + } + } + + } + +} diff --git a/Assets/ThirdParty/Org.OpenAPITools/Model/SubAssetFormat.cs.meta b/Assets/ThirdParty/Org.OpenAPITools/Model/SubAssetFormat.cs.meta new file mode 100644 index 0000000000..8c92bb92d4 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Model/SubAssetFormat.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f0c1a12ac7b184ba7938b44b8bdb1379 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThirdParty/Org.OpenAPITools/Model/User.cs b/Assets/ThirdParty/Org.OpenAPITools/Model/User.cs new file mode 100644 index 0000000000..965abe372c --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Model/User.cs @@ -0,0 +1,169 @@ +/* + * Icosa API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 0.1.0 + * Generated by: https://github.com/openapitools/openapi-generator.git + */ + + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.IO; +using System.Runtime.Serialization; +using System.Text; +using System.Text.RegularExpressions; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using Newtonsoft.Json.Linq; +using OpenAPIDateConverter = Org.OpenAPITools.Client.OpenAPIDateConverter; + +namespace Org.OpenAPITools.Model +{ + /// + /// User + /// + [DataContract(Name = "User")] + public partial class User : IEquatable + { + /// + /// Initializes a new instance of the class. + /// + [JsonConstructorAttribute] + protected User() { } + /// + /// Initializes a new instance of the class. + /// + /// url (required). + /// displayname (required). + /// description. + public User(string url = default(string), string displayname = default(string), string description = default(string)) + { + // to ensure "url" is required (not null) + if (url == null) + { + throw new ArgumentNullException("url is a required property for User and cannot be null"); + } + this.Url = url; + // to ensure "displayname" is required (not null) + if (displayname == null) + { + throw new ArgumentNullException("displayname is a required property for User and cannot be null"); + } + this.Displayname = displayname; + this.Description = description; + } + + /// + /// Gets or Sets Url + /// + [DataMember(Name = "url", IsRequired = true, EmitDefaultValue = true)] + public string Url { get; set; } + + /// + /// Gets or Sets Displayname + /// + [DataMember(Name = "displayname", IsRequired = true, EmitDefaultValue = true)] + public string Displayname { get; set; } + + /// + /// Gets or Sets Description + /// + [DataMember(Name = "description", EmitDefaultValue = false)] + public string Description { get; set; } + + /// + /// Returns the string presentation of the object + /// + /// String presentation of the object + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + sb.Append("class User {\n"); + sb.Append(" Url: ").Append(Url).Append("\n"); + sb.Append(" Displayname: ").Append(Displayname).Append("\n"); + sb.Append(" Description: ").Append(Description).Append("\n"); + sb.Append("}\n"); + return sb.ToString(); + } + + /// + /// Returns the JSON string presentation of the object + /// + /// JSON string presentation of the object + public virtual string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented); + } + + /// + /// Returns true if objects are equal + /// + /// Object to be compared + /// Boolean + public override bool Equals(object input) + { + return this.Equals(input as User); + } + + /// + /// Returns true if User instances are equal + /// + /// Instance of User to be compared + /// Boolean + public bool Equals(User input) + { + if (input == null) + { + return false; + } + return + ( + this.Url == input.Url || + (this.Url != null && + this.Url.Equals(input.Url)) + ) && + ( + this.Displayname == input.Displayname || + (this.Displayname != null && + this.Displayname.Equals(input.Displayname)) + ) && + ( + this.Description == input.Description || + (this.Description != null && + this.Description.Equals(input.Description)) + ); + } + + /// + /// Gets the hash code + /// + /// Hash code + public override int GetHashCode() + { + unchecked // Overflow is fine, just wrap + { + int hashCode = 41; + if (this.Url != null) + { + hashCode = (hashCode * 59) + this.Url.GetHashCode(); + } + if (this.Displayname != null) + { + hashCode = (hashCode * 59) + this.Displayname.GetHashCode(); + } + if (this.Description != null) + { + hashCode = (hashCode * 59) + this.Description.GetHashCode(); + } + return hashCode; + } + } + + } + +} diff --git a/Assets/ThirdParty/Org.OpenAPITools/Model/User.cs.meta b/Assets/ThirdParty/Org.OpenAPITools/Model/User.cs.meta new file mode 100644 index 0000000000..cd36ca59f3 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Model/User.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c57414deb298b432285541b5a494844e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThirdParty/Org.OpenAPITools/Model/ValidationError.cs b/Assets/ThirdParty/Org.OpenAPITools/Model/ValidationError.cs new file mode 100644 index 0000000000..32c59ac4be --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Model/ValidationError.cs @@ -0,0 +1,175 @@ +/* + * Icosa API + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 0.1.0 + * Generated by: https://github.com/openapitools/openapi-generator.git + */ + + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.IO; +using System.Runtime.Serialization; +using System.Text; +using System.Text.RegularExpressions; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using Newtonsoft.Json.Linq; +using OpenAPIDateConverter = Org.OpenAPITools.Client.OpenAPIDateConverter; + +namespace Org.OpenAPITools.Model +{ + /// + /// ValidationError + /// + [DataContract(Name = "ValidationError")] + public partial class ValidationError : IEquatable + { + /// + /// Initializes a new instance of the class. + /// + [JsonConstructorAttribute] + protected ValidationError() { } + /// + /// Initializes a new instance of the class. + /// + /// loc (required). + /// msg (required). + /// type (required). + public ValidationError(List loc = default(List), string msg = default(string), string type = default(string)) + { + // to ensure "loc" is required (not null) + if (loc == null) + { + throw new ArgumentNullException("loc is a required property for ValidationError and cannot be null"); + } + this.Loc = loc; + // to ensure "msg" is required (not null) + if (msg == null) + { + throw new ArgumentNullException("msg is a required property for ValidationError and cannot be null"); + } + this.Msg = msg; + // to ensure "type" is required (not null) + if (type == null) + { + throw new ArgumentNullException("type is a required property for ValidationError and cannot be null"); + } + this.Type = type; + } + + /// + /// Gets or Sets Loc + /// + [DataMember(Name = "loc", IsRequired = true, EmitDefaultValue = true)] + public List Loc { get; set; } + + /// + /// Gets or Sets Msg + /// + [DataMember(Name = "msg", IsRequired = true, EmitDefaultValue = true)] + public string Msg { get; set; } + + /// + /// Gets or Sets Type + /// + [DataMember(Name = "type", IsRequired = true, EmitDefaultValue = true)] + public string Type { get; set; } + + /// + /// Returns the string presentation of the object + /// + /// String presentation of the object + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + sb.Append("class ValidationError {\n"); + sb.Append(" Loc: ").Append(Loc).Append("\n"); + sb.Append(" Msg: ").Append(Msg).Append("\n"); + sb.Append(" Type: ").Append(Type).Append("\n"); + sb.Append("}\n"); + return sb.ToString(); + } + + /// + /// Returns the JSON string presentation of the object + /// + /// JSON string presentation of the object + public virtual string ToJson() + { + return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented); + } + + /// + /// Returns true if objects are equal + /// + /// Object to be compared + /// Boolean + public override bool Equals(object input) + { + return this.Equals(input as ValidationError); + } + + /// + /// Returns true if ValidationError instances are equal + /// + /// Instance of ValidationError to be compared + /// Boolean + public bool Equals(ValidationError input) + { + if (input == null) + { + return false; + } + return + ( + this.Loc == input.Loc || + this.Loc != null && + input.Loc != null && + this.Loc.SequenceEqual(input.Loc) + ) && + ( + this.Msg == input.Msg || + (this.Msg != null && + this.Msg.Equals(input.Msg)) + ) && + ( + this.Type == input.Type || + (this.Type != null && + this.Type.Equals(input.Type)) + ); + } + + /// + /// Gets the hash code + /// + /// Hash code + public override int GetHashCode() + { + unchecked // Overflow is fine, just wrap + { + int hashCode = 41; + if (this.Loc != null) + { + hashCode = (hashCode * 59) + this.Loc.GetHashCode(); + } + if (this.Msg != null) + { + hashCode = (hashCode * 59) + this.Msg.GetHashCode(); + } + if (this.Type != null) + { + hashCode = (hashCode * 59) + this.Type.GetHashCode(); + } + return hashCode; + } + } + + } + +} diff --git a/Assets/ThirdParty/Org.OpenAPITools/Model/ValidationError.cs.meta b/Assets/ThirdParty/Org.OpenAPITools/Model/ValidationError.cs.meta new file mode 100644 index 0000000000..eb01019141 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Model/ValidationError.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fe4140e4e47e24540b2aae9c9917dfea +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThirdParty/Org.OpenAPITools/Org.OpenAPITools.asmdef b/Assets/ThirdParty/Org.OpenAPITools/Org.OpenAPITools.asmdef new file mode 100644 index 0000000000..030e83ecf5 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Org.OpenAPITools.asmdef @@ -0,0 +1,7 @@ +{ + "name": "Org.OpenAPITools", + "overrideReferences": true, + "precompiledReferences": [ + "Newtonsoft.Json.dll" + ] +} diff --git a/Assets/ThirdParty/Org.OpenAPITools/Org.OpenAPITools.asmdef.meta b/Assets/ThirdParty/Org.OpenAPITools/Org.OpenAPITools.asmdef.meta new file mode 100644 index 0000000000..98790e8ff5 --- /dev/null +++ b/Assets/ThirdParty/Org.OpenAPITools/Org.OpenAPITools.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: c5c131588bc954ab8bd8d38e37ba847f +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ThirdParty/UltimateXR Keyboard/KeyboardKeyUI.cs b/Assets/ThirdParty/UltimateXR Keyboard/KeyboardKeyUI.cs index 6e6933176f..1fca2fcbc8 100644 --- a/Assets/ThirdParty/UltimateXR Keyboard/KeyboardKeyUI.cs +++ b/Assets/ThirdParty/UltimateXR Keyboard/KeyboardKeyUI.cs @@ -3,6 +3,7 @@ // Copyright (c) VRMADA, All rights reserved. // // -------------------------------------------------------------------------------------------------------------------- +using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.Localization; @@ -106,6 +107,7 @@ public class KeyboardKeyUI : MonoBehaviour [SerializeField] private TMPro.TMP_Text _multipleLayoutValueBottomLeft; [SerializeField] private TMPro.TMP_Text _multipleLayoutValueBottomRight; [SerializeField] private List _toggleSymbols; + [SerializeField] private UnityEngine.InputSystem.Key _keycode; // Hidden in the custom inspector [SerializeField] private bool _nameDirty; @@ -190,7 +192,7 @@ public void KeyDown() { _keyboard.KeyButton_KeyDown(this); } - + public void KeyUp() { _keyboard.KeyButton_KeyUp(this); @@ -379,6 +381,19 @@ private void Update() UpdateName(); } } + + // Support real keyboard input while open + if (_keycode != UnityEngine.InputSystem.Key.None) + { + if (UnityEngine.InputSystem.Keyboard.current[_keycode].wasPressedThisFrame) + { + KeyDown(); + } + if (UnityEngine.InputSystem.Keyboard.current[_keycode].wasReleasedThisFrame) + { + KeyUp(); + } + } } #endif diff --git a/Assets/ThirdParty/UltimateXR Keyboard/KeyboardUI.cs b/Assets/ThirdParty/UltimateXR Keyboard/KeyboardUI.cs index c0fb7bb0fd..f5003522aa 100644 --- a/Assets/ThirdParty/UltimateXR Keyboard/KeyboardUI.cs +++ b/Assets/ThirdParty/UltimateXR Keyboard/KeyboardUI.cs @@ -113,7 +113,7 @@ public bool CapsLockEnabled /// public string ConsoleContent { get; private set; } - public void SantizeFilename() + public void SanitizeFilename() { string invalidChars = System.Text.RegularExpressions.Regex.Escape(new string(System.IO.Path.GetInvalidFileNameChars())); string invalidRegStr = string.Format(@"([{0}]*\.+$)|([{0}]+)", invalidChars); @@ -301,12 +301,20 @@ protected void Awake() } } + private void OnDestroy() + { + InputManager.m_Instance.DisableKeyboardShortcuts = false; + } + /// /// If there is a console display Text component specified, it becomes updated with the content plus the cursor. /// If there is a caps lock GameObject specified it is updated to reflect the caps lock state as well. /// private void Update() { + // Disable global keyboard shortcuts while active so we can use real keyboard for input + InputManager.m_Instance.DisableKeyboardShortcuts = gameObject.activeInHierarchy; + if (_consoleDisplay != null) { _consoleDisplay.text = FormatStringOutput(_consoleDisplayUsesCursor ? ConsoleContentWithCursor : ConsoleContent, _consoleDisplayUsesCursor); diff --git a/Packages/manifest.json b/Packages/manifest.json index 8221486a4a..6ee8b482ad 100644 --- a/Packages/manifest.json +++ b/Packages/manifest.json @@ -10,7 +10,7 @@ "com.unity.cloud.ktx": "3.4.0", "com.unity.editorcoroutines": "1.0.0", "com.unity.formats.usd": "1.0.3-preview.2", - "com.unity.ide.rider": "3.0.31", + "com.unity.ide.rider": "3.0.34", "com.unity.ide.visualstudio": "2.0.22", "com.unity.inputsystem": "https://github.com/icosa-mirror/com.unity.inputsystem.git#1.8.2-openbrush", "com.unity.localization": "1.5.2", @@ -29,7 +29,7 @@ "com.unity.xr.oculus": "4.2.0", "com.unity.xr.openxr": "1.10.0", "com.zappar.xr.zapbox": "https://github.com/zappar-xr/zapbox-xr-sdk.git#43697771ed65efee02d5b1743141b8179444c147", - "org.khronos.unitygltf": "https://github.com/icosa-mirror/UnityGLTF.git", + "org.khronos.unitygltf": "https://github.com/icosa-mirror/UnityGLTF.git#feature/should-node-export-hook", "org.nuget.google.apis": "1.64.0", "org.nuget.google.apis.auth": "1.64.0", "org.nuget.google.apis.core": "https://github.com/icosa-mirror/org.nuget.google.apis.core.git#1.64.0-openbrush", diff --git a/Packages/packages-lock.json b/Packages/packages-lock.json index 6e0674c794..27a8690b78 100644 --- a/Packages/packages-lock.json +++ b/Packages/packages-lock.json @@ -124,7 +124,7 @@ "url": "https://packages.unity.com" }, "com.unity.ide.rider": { - "version": "3.0.31", + "version": "3.0.34", "depth": 0, "source": "registry", "dependencies": { @@ -371,7 +371,7 @@ "hash": "43697771ed65efee02d5b1743141b8179444c147" }, "org.khronos.unitygltf": { - "version": "https://github.com/icosa-mirror/UnityGLTF.git", + "version": "https://github.com/icosa-mirror/UnityGLTF.git#feature/should-node-export-hook", "depth": 0, "source": "git", "dependencies": { @@ -380,7 +380,7 @@ "com.unity.shadergraph": "10.0.0", "com.unity.mathematics": "1.0.0" }, - "hash": "99c96d9029d4ce02e5f729a5e069a44aef6faa99" + "hash": "59f0fd8d0722dd1156e0c4faf60964f841ced65b" }, "org.nuget.google.apis": { "version": "1.64.0", @@ -439,7 +439,7 @@ "depth": 0, "source": "git", "dependencies": {}, - "hash": "cff83f2ffcb95787572f951e7c7ea6e8958f2f65" + "hash": "731ce73482c74c1bccb84d53c1771f9c4a0d511b" }, "com.unity.modules.ai": { "version": "1.0.0", diff --git a/ProjectSettings/TagManager.asset b/ProjectSettings/TagManager.asset index f4a231f125..5068e998fe 100644 --- a/ProjectSettings/TagManager.asset +++ b/ProjectSettings/TagManager.asset @@ -31,7 +31,7 @@ TagManager: - GpuIntersection - PinnedStencilObject - Overlay - - + - Environment - - -